/**
 * 地图部分业务通用逻辑
 */

import Map from '@comp/MapBase'
import { desensitizeTeL } from '@utils'
import { getBindingLayersBySpecialSubjectCode, getPOIDataByParams, getConfigPOIDataDetail } from '@api/common'
import { cameraDetail } from '@api/dailyDispatching'

export const mapCommonMixin = {
  components: { Map },
  data() {
    return {
      topicType: this.$route.query.topicType || this.$route.meta.code,
      mapComponentRef: 'mapFrame', // 设置ref默认名称参数，默认为'mapFrame'
      mapComp: null, // 地图组件实例对象参数
      mapBasemapSelectWidgetShowFlag: true, // 地图底图切换微件展示标识参数，默认为true
      mapBoundsSwitchWidgetShowFlag: true, // 地图边界切换微件展示标识参数，默认为true
      mapToolsBarShowFlag: true, // 地图测量&圈画框选工具条微件展示标识参数，默认为true
      isShowLocationBarShowFlag: true, // 状态栏微件展示标识参数，默认为true
      clusterMode: 0, // 聚合模式参数，默认为0，可用值为：0-混合聚合模式，即使用“获取地图视野范围数据，小层级后端聚合，指定层级前端聚合，地图缩放移动实时刷新数据”的模式，1-前端聚合模式，即使用“初始获取全量数据，全层级前端聚合”
      frontClusterStartLevel: 14, // 混合聚合模式时前端聚合起始层级，默认为14
      defaultMapExtent: {}, // 默认地图范围对象组参数
      bindingLayerGroups: [], // 专题绑定的图层数组参数
      activateBindingLayerMode: 1, // POI查询-选中(激活)绑定图层的模式，默认值为1，可用值为：0-多选模式，1-单选模式
      activeBindingLayerIds: [], // POI查询-当前活动(选中)的绑定的图层id数组参数
      activeAreaCodes: [], //  POI查询-当前活动(选中)的绑定的行政区划编码数组参数
      activeSearchValue: '', // POI查询-当前活动(输入)的模糊查询值
      mapClickEventFlag: false, // 地图空白点击事件标识参数，默认为false
      customDescriptionInSummaryOfPOIDataByGraphicOnMap: '个调度资源', // 框选查询概览自定义描述
      paramsOfTransitiveFunction: [], // 传递函数所需的传参数组参数(传递POI的属性数据)
      showPOINameOnMapLimitLevel: 14, // POI名称开始展示层级配置参数，默认为14
      currentLayerGroupOfShowPrescriptivePOI: {}, // 当前展示指定POI的图层组对象参数
      propertyOfAllPOISOnCurrentShowPopup: [], // 当前展示popup的所包含全部POI的属性信息数组参数(popup分页基础参数)
      currentShowPopupPOIProperty: {}, // 当前展示popup的POI对应的属性对象参数
      reserveCurrentShowPopupPOIPropertyFlag: false, // 重置全局参数保留当前展示popup的POI对应的属性对象的标识参数，默认为false
      currentPagerPopupIndex: 1, // 分页的popup当前页码索引参数，默认为1
      currentPagerPopupCount: 1, // 分页的popup页码总数参数，默认为1
      popupContentLoading: false, // popup内容加载标识参数，默认为false
      currentShowPOIConfigDataDetail: {}, // 当前展示的POI数据对应的配置的详情信息
      popupCustomFields: [], // popup自定义字段对象数组参数，字段对象格式为:{ layerName: '', fieldName: '', dictionaryName: ''(可选), dictionaryData: [{ value: '', name: '' },...], showMatchedMode: { type: '', matchValue: '' }(可根据实际，进行扩展), htmlTemplateElement: { container: { height: number, start: '', end: '' }, content: { 0: { dynamicInsertValue: ''(实际传入匹配字段值，可选), start: '', end: '' },...(根据字典与实际值的比对匹配结果，进行构建) } } }
      popupCustomButtons: [], // popup自定义按钮对象数组参数，按钮对象格式为:{ layerName: '', buttonName: '', buttonFunctionName: '', buttonCreateJudgingConditions: [{ conditionName: '', conditionValues: [] }, ...], buttonFunctionParams: '' }
      popupGeneralButtonsGenerateFlag: {
        aggregatedButtonGenerateFlag: _const.mapConfigInfo.effectConfig.popupConfig.button.isAggregatedButtonShow, // 聚合类按钮生成标识，默认值为全局配置值
        commandAndDeployButtonGenerateFlag: _const.mapConfigInfo.effectConfig.popupConfig.button.singleGeneralButtonShow.commandAndDeployButton, // 指挥调度按钮生成标识，默认值为全局配置值
        voiceCallButtonGenerateFlag: _const.mapConfigInfo.effectConfig.popupConfig.button.singleGeneralButtonShow.voiceCallButton // 语音通话按钮生成标识，默认值为全局配置值
      }, // popup通用按钮生成标识
      currentOrderOfSurroundingSearchSelectedButtonOnPopup: {}, // 当前popup上的处于选中状态的周边搜索按钮排序号对象参数，默认为{}
      currentSurroundingSearchCircle: {}, // 当前周边搜索圆形对象参数，包含半径、经度、纬度
      useBuiltInSurroundingSearchShowDialog: _const.mapConfigInfo.interactConfig.useAssociatedComponent, // 周边搜索结果展示面板组件是否使用地图内置关联组件参数
      surroundingSearchCircleLayerName: 'surroundingSearchCircle', // 周边搜索圆形所在图层名称参数，默认为'surroundingSearchCircle'
      surroundingSearchResultPreferenceCustomSetting: 1 // 周边搜索结果图层展示首选项自定义设置，默认为1(默认选中首图层搜索结果)
    }
  },
  created() {
    // 全局函数映射绑定
    window.popupClose = this.popupClose // popup关闭按钮关闭函数映射绑定
    window.currentPagerPopupPagerController = this.currentPagerPopupPagerController // popup翻页控制器函数映射绑定
    window.imageView = this.imageView // (更多)图片查看函数映射绑定
    window.universalCommandAndDeploy = this.universalCommandAndDeploy // 通用的指挥调度函数映射绑定
    window.resourceCommandAndDeploy = this.resourceCommandAndDeploy // 特殊的(资源)指挥调度函数映射绑定
    window.voiceCall = this.voiceCall // 语音通话函数映射绑定
    window.showVideo = this.showVideo // 实时视频查看函数映射绑定
    window.showVR = this.showVR // 查看VR函数映射绑定
    window.searchSurroundingResources = this.searchSurroundingResources // 周边资源搜索函数映射绑定
  },
  mounted() {
    // 左键单击地图空白（未单击到矢量或模型数据）时鼠标事件监听
    this.$eventBus.$on('clickMap', () => {
      this.mapClickHandle() // 地图空白点击事件响应
    })
    // POI图层点击事件监听
    this.$eventBus.$on('POILayerClick', event => {
      this.POILayerClickHandle(event) // POI点击事件响应
    })
    // 地图popup打开事件监听
    this.$eventBus.$on('popupOpen', () => {
      this.updatePopup()
    })
    // 地图popup关闭事件监听
    this.$eventBus.$on('popupClose', event => {
      this.popupCloseHandle(event) // popup关闭事件响应
    })
    // 地图框选绘制完成事件监听
    this.$eventBus.$on('drawShapeOnMapCompleted', graphic => {
      this.searchPOIDataByGraphic(graphic) // 按照图形条件查询POI
    })
    // 地图外部触发POI高亮事件监听
    this.$eventBus.$on('POIHighlightWithOffMapTrigger', param => {
      if (!this.mapComp) {
        this.$message.warning('地图正在进行初始化加载，请稍后再试！')
        return
      }
      if (this.mapComp.dataLoading) {
        this.$message.warning('地图数据加载中，请稍后再试！')
        return
      }
      const isUniqueShowPOI = param.isUniqueShow !== false
      this.openPOIHighlight(param, isUniqueShowPOI) // 打开指定POI高亮显示
    })
    // 周边搜索结果展示面板使用外部视频资源展示面板，外部视频资源展示面板关闭事件监听
    if (!this.useBuiltInSurroundingSearchShowDialog) {
      this.$eventBus.$on('closeAroundCameraDialog', () => {
        this.clearSearchSurroundingResourcesMarkOnMap() // 清空周围资源搜索地图痕迹
      })
    }
  },
  beforeDestroy() {
    // 全局函数映射解绑
    window.popupClose = null
    window.currentPagerPopupPagerController = null
    this.imageView = null
    window.universalCommandAndDeploy = null
    window.resourceCommandAndDeploy = null
    window.voiceCall = null
    window.showVideo = null
    this.showVR = null
    window.searchSurroundingResources = null
    // 事件监听卸载
    this.$eventBus.$off('POILayerClick') // POI图层点击事件监听卸载
    this.$eventBus.$off('popupOpen') // popup打开事件监听卸载
    this.$eventBus.$off('popupClose') // popup关闭事件监听卸载
    this.$eventBus.$off('drawShapeOnMapCompleted') // 地图框选绘制完成事件监听卸载
    if (!this.useBuiltInSurroundingSearchShowDialog) this.$eventBus.$off('closeAroundCameraDialog') // 周边搜索结果展示面板为外部视频资源展示面板时，其关闭事件监听卸载
  },
  watch: {
    // 监听绑定图层集合数组参数变化，进行批量生成图层通用的自定义按钮(可扩展)
    bindingLayerGroups() {
      // 批量生成特殊的(资源)指挥调度按钮逻辑(指挥调度按钮生成标识全局配置作为生成依据)
      if (this.popupGeneralButtonsGenerateFlag.commandAndDeployButtonGenerateFlag) {
        const layerBlacklistOfResourceCommandAndDeployButton = ['视频监控', '网格员', '事件信息'] // 配置图层黑名单，名单内的图层将不会生成此按钮(可扩展)
        const resourceCommandAndDeployButtonConfig = {
          name: '指挥调度',
          functionName: 'resourceCommandAndDeploy',
          functionParams: ''
        }
        for (const item of this.bindingLayerGroups) {
          for (const subItem of item.layerInfoList) {
            if (layerBlacklistOfResourceCommandAndDeployButton.includes(subItem.layerName)) continue // 图层黑名单过滤
            this.popupCustomButtons.push({
              layerName: subItem.layerName,
              buttonName: resourceCommandAndDeployButtonConfig.name,
              buttonFunctionName: resourceCommandAndDeployButtonConfig.functionName,
              buttonFunctionParams: resourceCommandAndDeployButtonConfig.functionParams
            })
          }
        }
      }
    },
    // 监听currentShowPopupPOIProperty变化，进行关联逻辑处理
    currentShowPopupPOIProperty(newValue, oldValue) {
      if (JSON.stringify(oldValue) === '{}') {
        this.$eventBus.$emit('currentShowPopupPOIPropertyAdd', newValue)
      } else if (JSON.stringify(newValue) === '{}') {
        this.currentShowPOIConfigDataDetail = {}
        this.propertyOfAllPOISOnCurrentShowPopup = []
        this.$eventBus.$emit('currentShowPopupPOIPropertyRemove', oldValue)
      } else {
        this.currentShowPOIConfigDataDetail = {}
        this.$eventBus.$emit('currentShowPopupPOIPropertyUpdate', { newValue, oldValue })
      }
      if (newValue?.layerId !== oldValue?.layerId && oldValue?.layerId && !this.mapComp.getPOILayerMode(oldValue.layerId, 'show') && this.mapComp.getPOILayerMode(oldValue.layerId, 'click')) this.mapComp.businessLayers.POILayer[oldValue.layerId].show = false
    }
  },
  methods: {
    getMap() {
      this.mapComp = this.$refs[this.mapComponentRef]
      this.map = this.$refs[this.mapComponentRef].map
      this.defaultMapExtent = this.map.getExtent() // 获取默认的地图范围
    },
    // 外部更新当前POI数据查询全局参数
    updateActivePOIDataSearchParams(params) {
      this.activeBindingLayerIds = params.layerIds
      this.activeAreaCodes = params.areaCodes
      this.activeSearchValue = params.name ? params.name : ''
    },
    // 自主式获取绑定图层
    autonomousGetBindingLayers(isAutoLoadPOIData = true) {
      if (!this.mapComp) {
        setTimeout(() => {
          this.autonomousGetBindingLayers(isAutoLoadPOIData)
        }, 100)
        return
      }
      const param = {
        topicType: this.topicType
      }
      getBindingLayersBySpecialSubjectCode(param).then(res => {
        if (res.code === 200 && res.result) {
          let POILayers = []
          for (const item of res.result) {
            for (const subItem of item.layerInfoList) {
              subItem.showMode = item.isShow
              subItem.loadMode = item?.isClick ?? 0
            }
            POILayers = [...POILayers, ...item.layerInfoList]
          }
          this.mapComp.dynamicAddPOILayer(POILayers)
          this.waitingDynamicAddPOILayer(1, res.result)
        }
      })
    },
    // 被动式获取绑定图层
    controlledGetBindingLayers(bindingLayerIds) {
      if (!this.mapComp) {
        setTimeout(() => {
          this.controlledGetBindingLayers(bindingLayerIds)
        }, 100)
        return
      }
      this.mapComp.dynamicAddPOILayer(bindingLayerIds)
      this.waitingDynamicAddPOILayer()
    },
    // 等待POI图层加载完成后进行POI数据获取
    waitingDynamicAddPOILayer(funcIndex = 0, funcParam = null) {
      if (this.mapComp.dataLoadingMultiprocessingController.dynamicAddPOILayerProcess) {
        setTimeout(() => {
          this.waitingDynamicAddPOILayer(funcIndex, funcParam)
        }, 100)
      } else {
        if (funcIndex === 0) {
          this.loadPOIData(this.activeBindingLayerIds)
        } else {
          this.bindingLayerGroups = funcParam
        }
      }
    },
    // 按照图形条件查询POI数据
    searchPOIDataByGraphic(graphicCondition) {
      let extentParamType = null
      let extentParam = {
        center: graphicCondition.centerPoint // 几何中心 TODO: 多边形需要计算质心(turf)
      }
      switch (graphicCondition.type) {
        case 'circle':
          extentParamType = 1
          extentParam.circlePoint = graphicCondition.centerPoint // 圆心坐标
          extentParam.circleRadius = graphicCondition.radius / 1000 // 圆半径，单位基准为km
          break
        case 'rectangle':
          extentParamType = 2
          extentParam.rectangleExtent = graphicCondition.points // 矩形范围(左上角、右下角)数组
          break
        case 'polygon':
          extentParamType = 3
          extentParam.polygonPoints = graphicCondition.points // 多边形范围坐标串数组
          break
      }
      this.loadPOIData(this.activeBindingLayerIds, extentParamType, extentParam) // 根据框选地理范围数据获取POI数据
    },
    // 获取指定图层的POI数据
    // extentParamType: 数据请求地理范围参数类型，默认为0，可用值为：0-使用当前地图视野范围范围类型；1-使用传入的圆形范围类型；2-使用传入的矩形范围类型；3-使用传入的多边形范围类型
    loadPOIData(layerIds = [], extentParamType = 0, extentParam = {}, isUseLoadPOIAnimation = true, isRediscoverCurrentShowPopupPOI = true) {
      if (!layerIds.length) return
      // 传入参数layerIds参数特殊逻辑验证
      const hiddenDemandLoadModeLayerIds = layerIds.filter(item => {
        return !this.mapComp.getPOILayerMode(item, 'show') && this.mapComp.getPOILayerMode(item, 'click') // 获取传入参数layerIds中隐式展示的、隐式加载(按需加载)的图层id
      })
      // 验证条件：1.传入参数layerIds均为隐式展示的、隐式加载(按需加载)的图层的id，2.全局参数currentShowPopupPOIProperty对应的图层不包含在传入参数layerIds内
      if (hiddenDemandLoadModeLayerIds.length === layerIds.length && !layerIds.includes(this.currentShowPopupPOIProperty?.layerId)) return
      let isFrontCluster = false // 前端聚合标识参数，默认为false
      if (this.clusterMode || this.map.level >= this.frontClusterStartLevel) isFrontCluster = true // 前端聚合模式时或地图层级超过前端聚合起始层级时，更新聚合标识参数
      let currentMapExtent = this.map.getExtent() // 当前地图视野范围
      if (this.clusterMode) currentMapExtent = this.defaultMapExtent // 前端聚合模式时，重新设置POI数据请求地图范围为默认范围
      // 拼接请求参数
      const params = {
        name: this.activeSearchValue,
        areaCodeList: this.activeAreaCodes,
        layerIdList: layerIds,
        zoomLevel: this.map.level,
        needGroup: !isFrontCluster,
        topicType: this.topicType
      }
      // 根据传参，添加地理范围条件参数
      switch (extentParamType) {
        case 1:
          params.needGroup = false
          params.circleRadius = extentParam.circleRadius
          params.circlePoint = {
            fragment: true,
            geohash: '',
            lat: extentParam.circlePoint.lat,
            lon: extentParam.circlePoint.lng
          }
          break
        case 2:
          params.needGroup = false
          params.topLeft = {
            fragment: true,
            geohash: '',
            lat: extentParam.rectangleExtent[0].lat,
            lon: extentParam.rectangleExtent[0].lng
          }
          params.bottomRight = {
            fragment: true,
            geohash: '',
            lat: extentParam.rectangleExtent[1].lat,
            lon: extentParam.rectangleExtent[1].lng
          }
          break
        case 3:
          params.needGroup = false
          params.polygonPoints = []
          for (const item of extentParam.polygonPoints) {
            params.polygonPoints.push({
              fragment: true,
              geohash: '',
              lat: item.lat,
              lon: item.lng
            })
          }
          params.polygonPoints.push({
            fragment: true,
            geohash: '',
            lat: extentParam.polygonPoints[0].lat,
            lon: extentParam.polygonPoints[0].lng
          }) // 首尾归一
          break
        default:
          params.topLeft = {
            fragment: true,
            geohash: '',
            lat: currentMapExtent.ymax,
            lon: currentMapExtent.xmin
          }
          params.bottomRight = {
            fragment: true,
            geohash: '',
            lat: currentMapExtent.ymin,
            lon: currentMapExtent.xmax
          }
          break
      }
      // 数据请求获取
      this.mapComp.dataLoadingMultiprocessingController['loadPOIDataProcess'] = true
      this.mapComp.dataLoading = true
      getPOIDataByParams(params).then(res => {
        if (res.success) {
          let POIDataResult = res?.result
          if (!POIDataResult) {
            POIDataResult = {}
            for (const item of layerIds) POIDataResult[item] = []
          }
          if (!extentParamType) this.showPOIDataOnMap(POIDataResult, isFrontCluster, isUseLoadPOIAnimation, isRediscoverCurrentShowPopupPOI) // 数据上图
          else this.showSummaryOfPOIDataByGraphicOnMap(POIDataResult, extentParam.center, params) // 框选方式获取的数据概览(详情入口)上图
        } else {
          this.mapComp.dataLoadingMultiprocessingController['loadPOIDataProcess'] = false
          if (this.mapComp.judgeDataLoadingMultiprocessingControllerEndState()) this.mapComp.dataLoading = false
        }
      }).catch(() => {
        this.mapComp.dataLoadingMultiprocessingController['loadPOIDataProcess'] = false
        if (this.mapComp.judgeDataLoadingMultiprocessingControllerEndState()) this.mapComp.dataLoading = false
      })
    },
    // POI数据上图
    showPOIDataOnMap(data, isFrontCluster, useStartBounce = true, checkCurrentShowPopupOfLayer = false, isRediscoverCurrentShowPopupPOI = true, isIgnoreActivateBindingLayerModeCheck = false) {
      this.reserveCurrentShowPopupPOIPropertyFlag = true // 设置全局参数保留当前展示popup的POI对应的属性对象的标识参数(reserveCurrentShowPopupPOIPropertyFlag)为true，以实现POI数据重加载后恢复展示popup
      if (!isIgnoreActivateBindingLayerModeCheck && this.activateBindingLayerMode) {
        // 单选模式下，获取活动的绑定图层数组参数中存在的显式展示模式的图层
        const activeBindingShowStatusLayerIds = this.activeBindingLayerIds.filter(item => {
          return this.mapComp.getPOILayerMode(item, 'show')
        })
        if (activeBindingShowStatusLayerIds.length) this.mapComp.clearPOILayer(null, true) // 若获取到显式展示模式的图层，则需要清空全部的显式展示模式的POI图层
      }
      for (const layerId in data) {
        if (layerId === this.currentShowPopupPOIProperty?.layerId && !this.mapComp.getPOILayerMode(this.currentShowPopupPOIProperty.layerId, 'show') && this.mapComp.getPOILayerMode(this.currentShowPopupPOIProperty.layerId, 'click') && this.currentShowPopupPOIProperty?.isUniqueShowPOI && this.mapComp.businessLayers.POILayer[this.currentShowPopupPOIProperty.layerId].getGraphicByAttr(this.currentShowPopupPOIProperty.id, 'id')) continue // 当前展示popup的POI为唯一性显示且该POI在所在图层内存在，同时其所在图层为隐藏模式、POI加载模式为隐式加载(按需加载)情况下，不进行图层POI更新(不受地图姿态变化影响，保持POI的持续展示状态)
        this.mapComp.clearPOILayer(layerId) // 清空当前POI图层
        this.mapComp.businessLayers.POILayer[layerId].enabledEvent = false // 关闭事件
        if (this.currentLayerGroupOfShowPrescriptivePOI?.[layerId]) data[layerId] = this.currentLayerGroupOfShowPrescriptivePOI[layerId] // 展示指定POI的图层数据更新替换
        // 遍历数据，区分聚合点和POI点
        data[layerId].forEach(item => {
          if (!this.mapComp.checkLatlng(item.lat, 'lat') || !this.mapComp.checkLatlng(item.lng, 'lng')) return // 坐标合法性判别
          if (item.id) {
            // POI存在唯一性判别
            const graphicCheck = this.mapComp.businessLayers.POILayer[layerId].getGraphicByAttr(item.id, 'id')
            if (graphicCheck && graphicCheck.centerPoint.lat === Number(item.lat) && graphicCheck.centerPoint.lng === Number(item.lng)) return
          }
          let generalIcon = this.mapComp.POIIcon[layerId]
          if (item.layerIcon) {
            generalIcon = `${window._CONFIG['domianURL']}/${item.layerIcon}`
            if (item.layerIcon.substring(0, 4) === 'http') generalIcon = `${item.layerIcon}`
          }
          const graphic = new this.$Imap.graphic.BillboardEntity({
            position: [item.lng, item.lat],
            style: {
              image: generalIcon,
              width: (item.isGroup ? _const.mapConfigInfo.effectConfig.poiConfig.cluster.width : _const.mapConfigInfo.effectConfig.poiConfig.width) * this.mapComp.mapComponentSizeScale['--scaleX'],
              height: (item.isGroup ? _const.mapConfigInfo.effectConfig.poiConfig.cluster.height : _const.mapConfigInfo.effectConfig.poiConfig.height) * this.mapComp.mapComponentSizeScale['--scaleY'],
              horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
              verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
              visibleDepth: false,
              scale: 1,
              label: item.isGroup ? {
                text: `${item.size}`,
                font_size: _const.mapConfigInfo.effectConfig.poiConfig.label.top.fontSize * this.mapComp.mapComponentSizeScale['--scaleFontRelative'],
                font_weight: _const.mapConfigInfo.effectConfig.poiConfig.label.top.fontWeight,
                font_family: _const.mapConfigInfo.effectConfig.poiConfig.label.top.fontFamily,
                color: _const.mapConfigInfo.effectConfig.poiConfig.label.top.color,
                pixelOffsetY: -(_const.mapConfigInfo.effectConfig.poiConfig.cluster.height + _const.mapConfigInfo.effectConfig.poiConfig.label.top.spacing) * this.mapComp.mapComponentSizeScale['--scaleY'],
                visibleDepth: false
              } : this.map.level >= this.showPOINameOnMapLimitLevel ? {
                text: `${item.name}`,
                font_size: _const.mapConfigInfo.effectConfig.poiConfig.label.bottom.fontSize * this.mapComp.mapComponentSizeScale['--scaleFontRelative'],
                font_weight: _const.mapConfigInfo.effectConfig.poiConfig.label.bottom.fontWeight,
                font_family: _const.mapConfigInfo.effectConfig.poiConfig.label.bottom.fontFamily,
                color: _const.mapConfigInfo.effectConfig.poiConfig.label.bottom.color,
                pixelOffsetY: _const.mapConfigInfo.effectConfig.poiConfig.label.bottom.spacing * this.mapComp.mapComponentSizeScale['--scaleY'],
                fill: false,
                visibleDepth: false
              } : {} // 根据不同条件，加载不同的label，数据为后端聚合点时，label为聚合点数量展示，数据为POI点且地图层级超过POI名称展示配置的限制参数时，label为POI名称展示
            },
            attr: { isClusterPoint: !!item.isGroup, id: item.id, name: item.name, layerId: layerId } // 添加POI信息
          })
          this.mapComp.businessLayers.POILayer[layerId].addGraphic(graphic)
          if (useStartBounce) {
            // 使用跳动动画
            graphic.startBounce({
              maxHeight: 50,
              step: 10,
              autoStop: true
            })
          }
        })
        // 根据传入参数，控制图层聚合开关开闭
        if (isFrontCluster) this.mapComp.businessLayers.POILayer[layerId].clustering = true // 前端聚合标识参数为true时开启图层聚合
        else this.mapComp.businessLayers.POILayer[layerId].clustering = false // 前端聚合标识参数为false时关闭图层聚合
        this.mapComp.businessLayers.POILayer[layerId].enabledEvent = true // 恢复事件
      }
      this.mapComp.dataLoadingMultiprocessingController['loadPOIDataProcess'] = false
      if (this.mapComp.judgeDataLoadingMultiprocessingControllerEndState()) this.mapComp.dataLoading = false
      let dataForCheckingCurrentShowPopupOfLayer = {}
      if (checkCurrentShowPopupOfLayer) dataForCheckingCurrentShowPopupOfLayer = data
      if (isRediscoverCurrentShowPopupPOI) this.rediscoverCurrentShowPopupPOI(false, dataForCheckingCurrentShowPopupOfLayer) // 重发现POI对应的graphic
    },
    // 重发现当前需要展示popup的POI对应的graphic
    rediscoverCurrentShowPopupPOI(reserveCurrentShowPopupPOIProperty = true, dataForCheckingCurrentShowPopupOfLayer = {}) {
      if (JSON.stringify(this.currentShowPopupPOIProperty) === '{}') return
      let hasCurrentShowPopupOfLayerFlag = false
      if (JSON.stringify(dataForCheckingCurrentShowPopupOfLayer) !== '{}') {
        for (const layerId in dataForCheckingCurrentShowPopupOfLayer) {
          if (this.currentShowPopupPOIProperty.layerId === layerId) {
            hasCurrentShowPopupOfLayerFlag = true
            break
          }
        }
      }
      const graphic = this.mapComp.businessLayers.POILayer[this.currentShowPopupPOIProperty.layerId].getGraphicByAttr(this.currentShowPopupPOIProperty.id, 'id') // 根据属性id在打开popup的POI所属图层内查找POI的graphic对象
      if (graphic) {
        // 找到POI的graphic对象时，根据条件进行graphic更新popup相关操作
        if (JSON.stringify(dataForCheckingCurrentShowPopupOfLayer) !== '{}' && !hasCurrentShowPopupOfLayerFlag) {
          graphic.openHighlight() // 打开popup的POI不属于当前数据更新图层时，进行graphic(补充)高亮，并返回
          return
        }
        const delayGetClusterTime = 200 // 设置延时获取指定POI图层POI聚合点的时间参数(单位ms)，当前值为200
        // 进行延时操作，等待前端聚合动作完成
        setTimeout(() => {
          let currentPagerPopupIndex = 1 // popup翻页器当前页码索引，默认为1
          // 获取graphic所在图层的全部聚合点(由于图层不存在聚合点时getClusterList方法报错，故使用try...catch进行包装)
          try {
            // 获取聚合点后，需要区分3种数据变化情况：1.由POI聚合点变为POI点(不聚合)；2.由POI点(不聚合)变为POI聚合点；3.由旧的POI聚合点变为新的POI聚合点
            const POICluster = this.mapComp.businessLayers.POILayer[this.currentShowPopupPOIProperty.layerId].getClusterList() // 获取graphic所在图层当前的全部聚合点实体
            let clusterContainCurrentGraphic = {} // 定义包含当前graphic对象的POI聚合点实体对象参数
            let graphicsOfClusterContainCurrentGraphic = [] // 定义包含当前graphic对象的POI聚合点实体内全部graphic对象的数组参数
            // 遍历graphic所在图层当前的全部聚合点实体(POICluster)，查找包含当前graphic对象的POI聚合点实体，将查找结果(若找到)通过上述定义两参数进行存储
            for (const item of POICluster) {
              const graphicsOfCurrentCluster = item.getGraphics() // 使用聚合点api获取当前遍历的聚合点包含的全部graphic对象
              const rightGraphic = graphicsOfCurrentCluster.filter(subItem => {
                return subItem.attr.id === this.currentShowPopupPOIProperty.id && subItem.attr.layerId === this.currentShowPopupPOIProperty.layerId // 在当前遍历的聚合点包含的全部graphic对象中查找POI的graphic对象(使用currentShowPopupPOIProperty对象参数作为POI点属性)
              })
              if (rightGraphic.length) {
                // 查找结果存储，结束遍历查找逻辑
                clusterContainCurrentGraphic = item
                graphicsOfClusterContainCurrentGraphic = graphicsOfCurrentCluster
                break
              }
            }
            // 使用包含当前graphic对象的POI聚合点实体内全部graphic对象的数组参数(graphicsOfClusterContainCurrentGraphic)作为判断依据，区分不同数据变化情况
            if (graphicsOfClusterContainCurrentGraphic.length) {
              // 穿在包含目标POI的聚合点时，判断(判断依据为全局数组参数propertyOfAllPOISOnCurrentShowPopup长度值)区分1.由POI点变为POI聚合点，2.由旧的POI聚合点变为新的POI聚合点两种情况
              if (this.propertyOfAllPOISOnCurrentShowPopup.length === 1) {
                // 全局数组参数propertyOfAllPOISOnCurrentShowPopup长度为1时，认为是由POI点变为POI聚合点的情况，此时需要1.全量更新全局数组参数propertyOfAllPOISOnCurrentShowPopup，2.获取并更新popup翻页器当前页码索引参数currentPagerPopupIndex，3.更新位置信息(按需)
                this.propertyOfAllPOISOnCurrentShowPopup = []
                for (let index in graphicsOfClusterContainCurrentGraphic) {
                  this.propertyOfAllPOISOnCurrentShowPopup.push(graphicsOfClusterContainCurrentGraphic[index].attr) // graphic对象的attr属性保存
                  if (graphicsOfClusterContainCurrentGraphic[index].attr.id === this.currentShowPopupPOIProperty.id && graphicsOfClusterContainCurrentGraphic[index].attr.layerId === this.currentShowPopupPOIProperty.layerId) currentPagerPopupIndex = Number(index) + 1 // POI点在聚合点内顺序索引作为popup翻页器当前索引(从1开始计数)
                }
                if (!this.currentShowPopupPOIProperty.isUniqueShowPOI) graphic.position = clusterContainCurrentGraphic.position // 更新graphic对象位置信息(非唯一展示POI时)
              } else {
                // 全局数组参数propertyOfAllPOISOnCurrentShowPopup长度不为1时，判断是否由旧的POI聚合点变为新的POI聚合点的情况
                if (graphicsOfClusterContainCurrentGraphic.length === this.propertyOfAllPOISOnCurrentShowPopup.length) {
                  // 全局数组参数propertyOfAllPOISOnCurrentShowPopup长度与当前包含graphic的cluster中所有graphic的数组参数长度一致时，由于聚合点包含的graphic相同时，其内部graphic对象索引顺序可能发生变化，而此情况下处理逻辑与聚合点包含的graphic不同时一致，故默认以聚合点包含的graphic不同的情况进行处理
                  // 由旧的POI聚合点变为新的POI聚合点的情况，此时需要1.全量更新全局数组参数propertyOfAllPOISOnCurrentShowPopup，2.获取并更新popup翻页器当前页码索引参数currentPagerPopupIndex，3.更新位置信息(按需)
                  this.propertyOfAllPOISOnCurrentShowPopup = []
                  for (let index in graphicsOfClusterContainCurrentGraphic) {
                    this.propertyOfAllPOISOnCurrentShowPopup.push(graphicsOfClusterContainCurrentGraphic[index].attr) // graphic对象的attr属性保存
                    if (graphicsOfClusterContainCurrentGraphic[index].attr.id === this.currentShowPopupPOIProperty.id && graphicsOfClusterContainCurrentGraphic[index].attr.layerId === this.currentShowPopupPOIProperty.layerId) currentPagerPopupIndex = Number(index) + 1 // POI点在聚合点内顺序索引作为popup翻页器当前索引(从1开始计数)
                  }
                  if (!this.currentShowPopupPOIProperty.isUniqueShowPOI) graphic.position = clusterContainCurrentGraphic.position // 更新graphic位置信息(非唯一展示POI时)
                } else {
                  // 全局数组参数propertyOfAllPOISOnCurrentShowPopup长度与当前包含graphic的cluster中所有graphic的数组参数长度不一致时，认为是由旧的POI聚合点变为新的POI聚合点的情况，此时需要1.全量更新全局数组参数propertyOfAllPOISOnCurrentShowPopup，2.获取并更新popup翻页器当前页码索引参数currentPagerPopupIndex，3.更新位置信息(按需)
                  this.propertyOfAllPOISOnCurrentShowPopup = []
                  for (let index in graphicsOfClusterContainCurrentGraphic) {
                    this.propertyOfAllPOISOnCurrentShowPopup.push(graphicsOfClusterContainCurrentGraphic[index].attr) // graphic对象的attr属性保存
                    if (graphicsOfClusterContainCurrentGraphic[index].attr.id === this.currentShowPopupPOIProperty.id && graphicsOfClusterContainCurrentGraphic[index].attr.layerId === this.currentShowPopupPOIProperty.layerId) currentPagerPopupIndex = Number(index) + 1 // POI点在聚合点内顺序索引作为popup翻页器当前索引(从1开始计数)
                  }
                  if (!this.currentShowPopupPOIProperty.isUniqueShowPOI) graphic.position = clusterContainCurrentGraphic.position // 更新graphic位置信息(非唯一展示POI时)
                }
              }
            } else {
              // 聚合点中未包含POI点时，判断是否是由POI聚合点变为POI点的情况
              if (this.propertyOfAllPOISOnCurrentShowPopup.length > 1) {
                // 全局数组参数propertyOfAllPOISOnCurrentShowPopup长度超过1时，认为是由POI聚合点变为POI点的情况，此时需要定量更新全局数组参数propertyOfAllPOISOnCurrentShowPopup
                this.propertyOfAllPOISOnCurrentShowPopup = this.propertyOfAllPOISOnCurrentShowPopup.filter(item => {
                  return item.id === this.currentShowPopupPOIProperty.id && item.layerId === this.currentShowPopupPOIProperty.layerId // propertyOfAllPOISOnCurrentShowPopup过滤保留POI点关联信息，并自更新
                })
              }
            }
          } catch {
            // 图层当前不存在聚合点时，判断是否是由POI聚合点变为POI点的情况
            if (this.propertyOfAllPOISOnCurrentShowPopup.length > 1) {
              // 全局数组参数propertyOfAllPOISOnCurrentShowPopup长度超过1时，认为是由POI聚合点变为POI点的情况，此时需要定量更新全局数组参数propertyOfAllPOISOnCurrentShowPopup
              this.propertyOfAllPOISOnCurrentShowPopup = this.propertyOfAllPOISOnCurrentShowPopup.filter(item => {
                return item.id === this.currentShowPopupPOIProperty.id && item.layerId === this.currentShowPopupPOIProperty.layerId // propertyOfAllPOISOnCurrentShowPopup过滤保留POI点关联信息，并自更新
              })
            }
          }
          if (reserveCurrentShowPopupPOIProperty) this.reserveCurrentShowPopupPOIPropertyFlag = true // 根据传入参数reserveCurrentShowPopupPOIProperty设置，设置全局参数保留当前展示popup的POI对应的属性对象的标识参数(reserveCurrentShowPopupPOIPropertyFlag)为true，以实现popup动态更新展示
          if (this.currentShowPopupPOIProperty.isUniqueShowPOI) {
            // POI唯一展示标识存在时
            this.mapComp.businessLayers.POILayer[this.currentShowPopupPOIProperty.layerId].clear(false) // 清空图层
            this.mapComp.businessLayers.POILayer[this.currentShowPopupPOIProperty.layerId].addGraphic(graphic) // 重新添加重发现到的graphic
            // 全局参数propertyOfAllPOISOnCurrentShowPopup动态更新
            if (this.propertyOfAllPOISOnCurrentShowPopup.length > 1) {
              this.propertyOfAllPOISOnCurrentShowPopup = this.propertyOfAllPOISOnCurrentShowPopup.filter(item => {
                return item.id === this.currentShowPopupPOIProperty.id && item.layerId === this.currentShowPopupPOIProperty.layerId
              })
            }
            currentPagerPopupIndex = 1 // 当前翻页器页码索引参数重置为1
          }
          if (!this.mapComp.getPOILayerMode(this.currentShowPopupPOIProperty.layerId, 'show') && this.mapComp.getPOILayerMode(this.currentShowPopupPOIProperty.layerId, 'click')) this.mapComp.businessLayers.POILayer[this.currentShowPopupPOIProperty.layerId].show = true // 当POI所属图层为隐藏展示模式的POI隐式加载图层，需要显示图层
          this.bindPopup(graphic, currentPagerPopupIndex) // 为找到的graphic绑定popup
        }, delayGetClusterTime)
      } else {
        // 未找到POI的graphic对象时，针对特殊图层进行操作
        if (!this.mapComp.getPOILayerMode(this.currentShowPopupPOIProperty.layerId, 'show') && this.mapComp.getPOILayerMode(this.currentShowPopupPOIProperty.layerId, 'click')) this.mapComp.businessLayers.POILayer[this.currentShowPopupPOIProperty.layerId].show = false // 当POI所属图层为隐藏展示模式的POI隐式加载图层，需要重新隐藏图层
      }
    },
    // 地图空白点击事件响应
    mapClickHandle() {
      if (!this.mapComp.businessLayers?.POILayer?.[this.currentShowPopupPOIProperty?.layerId]?.show) return
      this.mapClickEventFlag = true // 地图空白点击事件标识参数设置为true
    },
    // popup关闭事件响应
    popupCloseHandle(event) {
      const currentShowPOIConfigDataDetailSnapshot = { ...this.currentShowPOIConfigDataDetail } // 深拷贝获取当前展示的POI数据对应的配置的详情信息参数快照(用于后续验证逻辑)
      const graphicSnapshot = { ...event.graphic.options }
      this.$eventBus.$emit('popupCloseOnMap', currentShowPOIConfigDataDetailSnapshot) // 发射指令，提供给地图关联组件，用于地图关联组件业务逻辑
      if (!this.useBuiltInSurroundingSearchShowDialog) this.$eventBus.$emit('popupCloseOnMapForAroundCameraDialog') // 周边搜索使用外部视频资源展示面板展示结果时，发射专用指令(popupCloseOnMapForAroundCameraDialog)
      // 根据事件发生时，关闭的popup所绑定的graphic的类型(POI点或聚合点)，进行popup相关逻辑处理
      if (this.currentPagerPopupCount === 1) {
        // 使用全局参数分页的popup页码总数(currentPagerPopupCount)，作为判断graphic的类型的依据，其值为1时，认为对应的类型是POI点
        // 设置延时执行逻辑，确保点击地图空白事件响应优先完成，保证正确逻辑执行
        setTimeout(() => {
          // 基于全局参数地图空白点击事件标识参数(mapClickEventFlag)取值(延时获取)，判断当前popup关闭事件是否由点击地图空白事件触发
          if (this.mapClickEventFlag) {
            // 全局参数地图空白点击事件标识参数(mapClickEventFlag)为true时，认为当前popup关闭事件由点击地图空白事件触发，进行相关全局参数取值调整
            this.mapClickEventFlag = false // 重置全局参数地图空白点击事件标识参数(mapClickEventFlag)为false(避免影响后续点击矢量对象情形的判断)
            this.reserveCurrentShowPopupPOIPropertyFlag = false // 设置全局参数保留当前展示popup的POI对应的属性对象的标识参数(reserveCurrentShowPopupPOIPropertyFlag)为false，以便后续进行全局参数当前展示popup的POI对应的属性对象参数(currentShowPopupPOIProperty)置空操作
          }
          this.resetCurrentShowPopupPOIProperty(graphicSnapshot) // 重置全局参数currentShowPopupPOIProperty
        })
      } else {
        // 全局参数分页的popup页码总数(currentPagerPopupCount)取值大于1时，认为对应的类型是聚合点(聚合点时，打开的popup绑定的graphic实质为聚合点内部的POI点，故按照POI点相关处理逻辑进行处理)，根据当前关闭的popup绑定的graphic所在图层的活动状态，进行popup相关逻辑处理
        if (this.activeBindingLayerIds.includes(this.currentShowPopupPOIProperty.layerId)) {
          // 当前关闭的popup绑定的graphic所在图层处于活动状态时，设置延时执行逻辑，确保点击地图空白事件响应优先完成，保证正确逻辑执行
          setTimeout(() => {
            // 基于全局参数地图空白点击事件标识参数(mapClickEventFlag)取值(延时获取)，判断当前popup关闭事件是否由点击地图空白事件触发
            if (this.mapClickEventFlag) {
              // 全局参数地图空白点击事件标识参数(mapClickEventFlag)为true时，认为当前popup关闭事件由点击地图空白事件触发，执行相关逻辑
              this.mapClickEventFlag = false // 重置全局参数地图空白点击事件标识参数(mapClickEventFlag)为false(避免影响后续点击矢量对象情形的判断)
              this.reserveCurrentShowPopupPOIPropertyFlag = false // 设置全局参数保留当前展示popup的POI对应的属性对象的标识参数(reserveCurrentShowPopupPOIPropertyFlag)为false，以便后续进行全局参数当前展示popup的POI对应的属性对象参数(currentShowPopupPOIProperty)置空操作
            } else {
              // 全局参数地图空白点击事件标识参数(mapClickEventFlag)为false时，则当前popup关闭事件不是由点击地图空白事件触发，认为当前popup关闭事件是否由1刷新事件或2点击聚合点事件触发。根据相关参数，判断当前popup关闭事件是否由点击同一聚合点事件触发
              if (this.propertyOfAllPOISOnCurrentShowPopup.length > 1) {
                // 当前展示popup的所包含全部POI的属性信息数组参数(propertyOfAllPOISOnCurrentShowPopup)数量大于1(聚合点)，判断当前popup关闭事件是否由点击同一聚合点事件触发
                let isClickSameClusterVerifiedArray = []
                if (JSON.stringify(currentShowPOIConfigDataDetailSnapshot) !== '{}') {
                  isClickSameClusterVerifiedArray = this.propertyOfAllPOISOnCurrentShowPopup.filter(item => {
                    return item.id === currentShowPOIConfigDataDetailSnapshot.data.id && item.layerId === currentShowPOIConfigDataDetailSnapshot.layerId
                  })
                }
                if (isClickSameClusterVerifiedArray.length || JSON.stringify(currentShowPOIConfigDataDetailSnapshot) === '{}') event.graphic.openPopup() // 当前popup关闭事件由再次点击该聚合点事件触发时，执行手动打开popup
              }
            }
            this.resetCurrentShowPopupPOIProperty(graphicSnapshot, true) // 重置全局参数currentShowPopupPOIProperty
          })
        }
      }
    },
    // 重置currentShowPopupPOIProperty参数以及关联参数
    resetCurrentShowPopupPOIProperty(graphic, isCluster = false) {
      if (this.reserveCurrentShowPopupPOIPropertyFlag) {
        this.reserveCurrentShowPopupPOIPropertyFlag = false
        return
      }
      if (graphic.attr && graphic.attr.layerId === this.currentShowPopupPOIProperty.layerId && (isCluster || graphic.attr.id === this.currentShowPopupPOIProperty.id)) this.currentShowPopupPOIProperty = {}
    },
    // POI点击事件响应
    POILayerClickHandle(event) {
      if (event.type !== 'click') {
        // 对来自非POI图层点击事件的数据进行预处理
        let graphic = {}
        // 根据pickedObject属性来获取当前点击的graphic
        if (Array.isArray(event.pickedObject.id) && event.pickedObject.id.length) {
          // 聚合点时，轮询获取当前点击graphic所在的聚合点graphic
          const currentClusters = this.mapComp.businessLayers.POILayer[event.layer.id].getClusterList() // 获取当前点击的graphic所在图层当前所有的聚合点
          for (const item of currentClusters) {
            let breakFlag = false
            for (const subItem of item.entities) {
              if (subItem.id === event.pickedObject.id[0].id) {
                breakFlag = true
                break
              }
            }
            if (breakFlag) {
              graphic = item // 获取到当前点击graphic所在的聚合点graphic信息
              break
            }
          }
        } else {
          graphic = this.mapComp.businessLayers.POILayer[event.layer.id].getGraphicByAttr(event.pickedObject.id.id, 'id') // 非聚合点时，获取当前点击graphic的graphic信息
        }
        if (!Object.keys(graphic).length) return
        event.graphic = graphic // 为事件响应传参中的graphic重新赋值
      }
      // 优先处理popup已经打开时的相关逻辑
      if (!event.graphic.cluster) {
        // 非前端聚合点情况
        if (event.graphic.getPopup()) {
          // 若此点击的POI点的popup处于打开状态时，进行手动关闭
          this.reserveCurrentShowPopupPOIPropertyFlag = false // 更新设置全局参数保留当前展示popup的POI对应的属性对象的标识参数(reserveCurrentShowPopupPOIPropertyFlag)为false，以便后续进行全局参数当前展示popup的POI对应的属性对象参数(currentShowPopupPOIProperty)置空操作，保证图层重加载后不再展示该popup
          // 在此点击的POI点所在图层中查找其对应的graphic，并进行popup事件和highlight事件的解绑
          const graphic = this.mapComp.businessLayers.POILayer[event.graphic.attr.layerId].getGraphicByAttr(event.graphic.attr.id, 'id')
          if (graphic) {
            graphic.closePopup()
            graphic.unbindPopup()
            graphic.unbindHighlight()
          }
          return
        }
      } else {
        // 前端聚合点情况
        // 遍历聚合点的全部POI点，查找聚合点内打开的popup所绑定的POI点，并进行popup事件和highlight事件的解绑
        let returnFlag = false // 设置结束逻辑标识，用于判断逻辑结束与否的依据，初始取值为false
        for (const item of event.graphic.getGraphics()) {
          // 遍历聚合点的POI点
          if (item.getPopup()) {
            // 找到聚合点内的POI点的popup处于打开状态时，进行手动关闭
            returnFlag = true // 更新设置结束逻辑标识为true
            this.reserveCurrentShowPopupPOIPropertyFlag = false // 更新设置全局参数保留当前展示popup的POI对应的属性对象的标识参数(reserveCurrentShowPopupPOIPropertyFlag)为false，以便后续进行全局参数当前展示popup的(聚合点内)POI点对应的属性对象参数(currentShowPopupPOIProperty)置空操作，保证图层重加载后不再展示该popup
            // 在此点击的聚合点所在图层中查找该POI点对应的graphic，并进行popup事件和highlight事件的解绑
            const graphic = this.mapComp.businessLayers.POILayer[item.attr.layerId].getGraphicByAttr(item.attr.id, 'id')
            if (graphic) {
              graphic.closePopup()
              graphic.unbindPopup()
              graphic.unbindHighlight()
            }
            break
          }
        }
        if (returnFlag) return
      }
      // 再处理popup未打开时的相关逻辑
      if (!event.graphic.cluster) {
        // 非前端聚合点情况
        if (!event.graphic.attr.isClusterPoint) {
          // POI点,处理弹出popup逻辑
          this.propertyOfAllPOISOnCurrentShowPopup = [event.graphic.attr] // 全局参数当前展示popup的所包含全部POI的属性信息数组参数(propertyOfAllPOISOnCurrentShowPopup)赋值为当前POI点属性
          // 全局参数当前展示popup的POI对应的属性对象参数(currentShowPopupPOIProperty)赋值为当前POI点属性信息
          this.currentShowPopupPOIProperty = {
            id: event.graphic.attr.id,
            layerId: event.graphic.attr.layerId
          }
          const coordinate = event.graphic.centerPoint // 获取POI点坐标
          coordinate.alt = this.map.getCameraView().alt
          if (this.isMapCenterWithTheLocation(coordinate)) {
            // POI点处于地图中心点时
            this.reserveCurrentShowPopupPOIPropertyFlag = true // 设置全局参数保留当前展示popup的POI对应的属性对象的标识参数(reserveCurrentShowPopupPOIPropertyFlag)为true，以实现POI数据重加载后恢复展示该popup
            const graphic = this.mapComp.businessLayers.POILayer[event.graphic.attr.layerId].getGraphicByAttr(event.graphic.attr.id, 'id')
            this.bindPopup(graphic) // POI点直接打开popup
          } else {
            this.mapStatusSwitch(2, coordinate, true) // POI点非处于地图中心点时，移动地图中心至指定点
          }
        } else {
          // 后端聚合点情况，由聚合点位置放大地图层级+2
          this.reserveCurrentShowPopupPOIPropertyFlag = false // 更新设置全局参数保留当前展示popup的POI对应的属性对象的标识参数(reserveCurrentShowPopupPOIPropertyFlag)为false，以便后续进行全局参数当前展示popup的(聚合点内)POI点对应的属性对象参数(currentShowPopupPOIProperty)置空操作，保证图层重加载后不再展示该popup
          const targetMapStatus = {
            lat: event.graphic.point.lat,
            lng: event.graphic.point.lng,
            alt: this.mapComp.convertZoomToAltitude(this.map.level + 2)
          }
          this.mapStatusSwitch(2, targetMapStatus) // 更新地图状态
        }
      } else {
        // 前端聚合点情况，处理聚合点弹出popup逻辑
        // 遍历聚合点内的全部POI点，进行相关参数获取
        // 全局参数当前展示popup的所包含全部POI的属性信息数组参数(propertyOfAllPOISOnCurrentShowPopup)逐个添加聚合点内的POI点属性
        this.propertyOfAllPOISOnCurrentShowPopup = []
        for (const item of event.id) {
          const template = {}
          for (const subItem of item.properties.propertyNames) template[subItem] = item.properties[subItem]._value
          this.propertyOfAllPOISOnCurrentShowPopup.push(template)
        }
        // 全局参数当前展示popup的POI对应的属性对象参数(currentShowPopupPOIProperty)赋值为聚合点内遍历的第一个的POI点属性信息
        this.currentShowPopupPOIProperty = {
          id: this.propertyOfAllPOISOnCurrentShowPopup[0].id,
          layerId: this.propertyOfAllPOISOnCurrentShowPopup[0].layerId
        }
        const coordinate = this.$Imap.LngLatPoint.fromCartesian(event.graphic.cluster.point.position) // 获取聚合点坐标
        coordinate.alt = this.map.getCameraView().alt
        if (this.isMapCenterWithTheLocation(coordinate)) {
          // 聚合点处于地图中心点时
          this.reserveCurrentShowPopupPOIPropertyFlag = true // 设置全局参数保留当前展示popup的POI对应的属性对象的标识参数(reserveCurrentShowPopupPOIPropertyFlag)为true，以实现POI数据重加载后恢复展示该popup
          const graphic = event.graphic.getGraphics()[0] // 获取聚合点内第一个的POI点对应的graphic对象
          graphic.position = event.graphic.cluster.point.position // 更新graphic对象位置数据为聚合点位置
          this.bindPopup(graphic) // 打开popup
        } else {
          this.mapStatusSwitch(2, coordinate, true) // 聚合点非处于地图中心点时，移动地图中心至指定点
        }
      }
    },
    // popup模板绑定
    bindPopup(graphic, pagerPopupIndex = 1) {
      this.currentPagerPopupCount = this.propertyOfAllPOISOnCurrentShowPopup.length // popup总页数
      this.currentPagerPopupIndex = pagerPopupIndex > this.currentPagerPopupCount ? this.currentPagerPopupCount : pagerPopupIndex // 当前页码索引(一并进行越界检查限制)
      let content = ''
      let popupContentLoadingCalculateHeightMinus = (this.mapComp.mapPopupConfig.currentConfig.titleHeight + this.mapComp.mapPopupConfig.currentConfig.defaultHeight * (1 - this.mapComp.mapPopupConfig.currentConfig.contentHeightProportion)) * this.mapComp.mapComponentSizeScale['--scaleY'] // 根据popup配置，计算loading内容部分高度的减数(计算公式：(popup内容标题部分高度+popup计算初始默认高度*(1-popup内容部分高度与popup容器占比率值))*地图组件尺寸Y轴缩放系数)
      if (this.currentPagerPopupCount > 1) popupContentLoadingCalculateHeightMinus = popupContentLoadingCalculateHeightMinus + this.mapComp.mapPopupConfig.currentConfig.pagerHeight * this.mapComp.mapComponentSizeScale['--scaleY'] // 翻页控制器存在时，减数需加上popup配置的翻页控制器高度(比例计算后的结果值)
      // 拼接popup(分页)内容模板
      for (let index in this.propertyOfAllPOISOnCurrentShowPopup) {
        content += `
          <div id="page-${Number(index) + 1}" style="display: ${Number(index) + 1 === this.currentPagerPopupIndex ? 'block' : 'none'};">
            <div class="title">
              <div class="name">
                <div class="scroll-wrap">
                  <div class="scroll-item">
                    ${this.propertyOfAllPOISOnCurrentShowPopup[index].name}
                  </div>
                </div>
              </div>
              <div class="button" onclick="popupClose()"></div>
            </div>
            <div id="page-${Number(index) + 1}-description" class="description" style="height: calc(100% - ${popupContentLoadingCalculateHeightMinus}px); border-bottom-width: ${this.currentPagerPopupCount > 1 ? '0' : 'initial'};">
              ${this.createPopupContentLoadingTemplate()}
            </div>
          </div>
        `
      }
      if (this.currentPagerPopupCount > 1) {
        // 存在分页时,拼接页码控制模板
        content += `<div id="pager-container" class="pager-container">`
        if (this.$store.state.visual.scaleStyle) content += `<div class="fill-gap"></div>`
        content += `
            <p class="pager-button pager-button-back" style="display: ${this.currentPagerPopupIndex === 1 ? 'none' : 'block'};" onclick="currentPagerPopupPagerController(1)"></span>
            <p id="currentClusterInfoWindowIndexer">${this.currentPagerPopupIndex}</p>/<p>${this.currentPagerPopupCount}</p>
            <p class="pager-button pager-button-next" style="display: ${this.currentPagerPopupIndex === this.currentPagerPopupCount ? 'none' : 'block'};" onclick="currentPagerPopupPagerController(2)"></p>
          </div>
        `
      }
      // 根据popup展示类型参数配置，动态拼接生成popup模板html片段
      const contentClass = this.currentPagerPopupCount > 1 ? `content has-pager` : `content` // 根据分页情况，动态拼接生成content的class名称(添加分页存在标识class(has-pager))
      const template = `
        <div class="map-popup">
          <div class="map-popup-type-${this.mapComp.mapPopupShowType}">
            <div class="line"></div>
            <div id="content-container" class="content-container">
              <div id="content" class="${contentClass}">{content}</div>
            </div>
          </div>
        </div>
      `
      graphic.bindPopup(content, {
        template: template,
        zIndex: 2,
        horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
        verticalOrigin: Cesium.VerticalOrigin.TOP
      })
      graphic.openPopup()
      graphic.bindHighlight({
        type: 'click',
        scale: 1.5
      }) // 绑定放大(高亮突出)当前POI点事件
      graphic.openHighlight()
    },
    // 生成popup详情内容loading的html模板
    createPopupContentLoadingTemplate() {
      const template = `
        <div class="loading">
          <div class="spinner">
            <svg viewBox="25 25 50 50" class="circular">
              <circle cx="50" cy="50" r="20" fill="none" class="path"></circle>
            </svg>
          </div>
        </div>
      `
      return template
    },
    // popup关闭按钮关闭方法
    popupClose() {
      this.mapClickHandle() // 模拟触发地图空白点击事件
      this.map.closePopup() // 手动关闭popup
      this.map.closeHighlight() // 手动关闭POI高亮
    },
    // 分页的popup翻页控制器
    currentPagerPopupPagerController(command) {
      if (this.popupContentLoading) {
        this.$message.warning('正在加载数据，请稍等！')
        return
      }
      if (!(this.currentPagerPopupIndex >= 1 && this.currentPagerPopupIndex <= this.currentPagerPopupCount)) return // 页码变更越界检查控制
      const currentPagerPopupIndexSnapshot = this.currentPagerPopupIndex
      // 根据传参，更新全局当前页码索引参数currentPagerPopupIndex
      switch (command) {
        case 1:
          if (this.currentPagerPopupIndex - 1 < 1) return // 页码越界逻辑性检查
          this.currentPagerPopupIndex-- // 上一页
          break
        case 2:
          if (this.currentPagerPopupIndex + 1 > this.currentPagerPopupCount) return // 页码越界逻辑性检查
          this.currentPagerPopupIndex++ // 下一页
          break
        default:
          return
      }
      // 翻页控制器UI控制动态更新
      $('.pager-button-back').css({ 'display': `${this.currentPagerPopupIndex === 1 ? 'none' : 'block'}` }) // 按钮-上一页
      $('.pager-button-next').css({ 'display': `${this.currentPagerPopupIndex === this.currentPagerPopupCount ? 'none' : 'block'}` }) // 按钮-下一页
      $('#currentClusterInfoWindowIndexer').html(this.currentPagerPopupIndex) // 当前页码
      // popup内容更新
      $(`#page-${currentPagerPopupIndexSnapshot}`).hide() // 隐藏翻页前的页码对应的popup
      $(`#page-${this.currentPagerPopupIndex}`).show() // 展示当前页码对应的popup
      // 恢复重置popup整体样式动态调整的部分
      $('#content-container').removeAttr('style')
      $('#content').removeAttr('style')
      $('#pager-container').removeAttr('style')
      // 恢复翻页前的页码对应的popup为初始状态
      $(`#page-${currentPagerPopupIndexSnapshot}-description`).empty()
      const popupContentLoadingCalculateHeightMinus = (this.mapComp.mapPopupConfig.currentConfig.titleHeight + this.mapComp.mapPopupConfig.currentConfig.defaultHeight * (1 - this.mapComp.mapPopupConfig.currentConfig.contentHeightProportion) + this.mapComp.mapPopupConfig.currentConfig.pagerHeight) * this.mapComp.mapComponentSizeScale['--scaleY'] // 根据popup配置，计算存在翻页控制器时，loading内容部分高度的减数(计算公式：(popup内容标题部分高度+popup计算初始默认高度*(1-popup内容部分高度与popup容器占比率值)+翻页控制器高度)*地图组件尺寸Y轴缩放系数)
      $(`#page-${currentPagerPopupIndexSnapshot}-description`).css('height', `calc(100% - ${popupContentLoadingCalculateHeightMinus}px)`)
      $(`#page-${currentPagerPopupIndexSnapshot}-description`).prepend(this.createPopupContentLoadingTemplate())
      // 更新当前页码对应的popup
      this.currentShowPopupPOIProperty = {
        id: this.propertyOfAllPOISOnCurrentShowPopup[this.currentPagerPopupIndex - 1].id,
        layerId: this.propertyOfAllPOISOnCurrentShowPopup[this.currentPagerPopupIndex - 1].layerId
      }
      this.updatePopup()
    },
    // 更新popup详情内容
    updatePopup() {
      // 请求对象参数创建并添加通用请求参数
      const param = {
        id: this.currentShowPopupPOIProperty.id,
        layerId: this.currentShowPopupPOIProperty.layerId
      }
      // 添加特殊请求参数
      const generalParameterList = ['name', 'layerId', 'id', 'isClusterPoint'] // 排除参数列表
      for (const key in this.propertyOfAllPOISOnCurrentShowPopup[this.currentPagerPopupIndex - 1]) {
        if (!generalParameterList.includes(key)) {
          param[key] = this.propertyOfAllPOISOnCurrentShowPopup[this.currentPagerPopupIndex - 1][key] // 遍历传递参数对象，添加特殊请求参数
        }
      }
      const scalePopupAppearanceParametersConfig = {
        thresholdOfContentFromBottom: this.mapComp.mapPopupConfig.currentConfig.thresholdOfContentFromBottom * this.mapComp.mapComponentSizeScale['--scaleY'],
        titleHeight: this.mapComp.mapPopupConfig.currentConfig.titleHeight * this.mapComp.mapComponentSizeScale['--scaleY'],
        pagerHeight: this.mapComp.mapPopupConfig.currentConfig.pagerHeight * this.mapComp.mapComponentSizeScale['--scaleY']
      }
      this.popupContentLoading = true
      getConfigPOIDataDetail(param).then(res => {
        if (res.code === 200 && res.result) {
          this.currentShowPOIConfigDataDetail = res.result // 保存更新当前展示POI数据详情信息至全局变量currentShowPOIConfigDataDetail中
          this.$eventBus.$emit('popupOpenOnMap', this.currentShowPOIConfigDataDetail) // 发射指令，提供给地图关联组件，用于地图关联组件业务逻辑
          const { buttonContent, buttonHeight } = res.result.data ? this.popupButtonContentInstance(res.result.layerName, res.result.layerId, res.result.data) : { buttonContent: 0, buttonHeight: 0 } // 按钮内容实例化
          const { indexContent, indexHeight } = this.popupIndexContentInstance(res.result.data, res.result.labels, buttonHeight) // 指标内容实例化
          const content = indexContent + buttonContent // 获取全部内容(指标内容+按钮内容)
          let currentPopupContentHeight = scalePopupAppearanceParametersConfig.titleHeight + indexHeight + buttonHeight // 计算当前popup内容部分高度(计算公式:当前popup内容部分高度=标题部分高度+指标部分高度+按钮部分高度)
          if (this.currentPagerPopupCount > 1) currentPopupContentHeight += scalePopupAppearanceParametersConfig.pagerHeight // 存在分页时，当前popup内容部分高度重新计算(计算公式:当前popup内容部分高度=当前popup内容部分高度+页码部分高度)
          const currentPopupHeight = currentPopupContentHeight / this.mapComp.mapPopupConfig.currentConfig.contentHeightProportion // 计算当前popup自适应高度(计算公式:当前popup内容部分高度/popup内容部分高度与popup容器占比率值)
          $('#content-container').css({ 'height': `${currentPopupHeight}px`, 'bottom': `${scalePopupAppearanceParametersConfig.thresholdOfContentFromBottom - currentPopupHeight}px` }) // 设置popup内容容器高度以及位置(bottom)
          $('#content').css({ 'height': `calc(100% - ${currentPopupHeight * (this.mapComp.mapPopupConfig.currentConfig.contentMarginTopProportion + this.mapComp.mapPopupConfig.currentConfig.contentMarginBottomProportion)}px)`, 'margin-top': `${currentPopupHeight * this.mapComp.mapPopupConfig.currentConfig.contentMarginTopProportion}px`, 'margin-bottom': `${currentPopupHeight * this.mapComp.mapPopupConfig.currentConfig.contentMarginBottomProportion}px` }) // 设置popup内容高度以及margin
          if (this.currentPagerPopupCount > 1) $('#pager-container').css('bottom', `${currentPopupHeight * this.mapComp.mapPopupConfig.currentConfig.contentMarginBottomProportion}px`) // 存在分页时，设置页码容器位置(bottom)
          $(`#page-${this.currentPagerPopupIndex}-description`).empty() // 移除当前页码内容(指标内容+按钮内容)容器中加载(loading)dom节点
          let otherHeight = scalePopupAppearanceParametersConfig.titleHeight + currentPopupHeight * (this.mapComp.mapPopupConfig.currentConfig.contentMarginTopProportion + this.mapComp.mapPopupConfig.currentConfig.contentMarginBottomProportion) // 计算当前指标内容和按钮内容之外部分高度(计算公式:当前指标内容和按钮内容之外部分高度=标题部分高度+外观留白部分高度(计算公式:当前popup自适应高度*(popup内容部分上部margin与popup容器占比率值+popup内容部分下部margin与popup容器占比率值)))
          if (this.currentPagerPopupCount > 1) otherHeight += scalePopupAppearanceParametersConfig.pagerHeight // 存在分页时，当前指标内容和按钮内容之外部分高度重新计算(计算公式:当前指标内容和按钮内容之外部分高度=当前指标内容和按钮内容之外部分高度+页码部分高度)
          $(`#page-${this.currentPagerPopupIndex}-description`).css('height', `calc(100% - ${otherHeight}px)`) // 设置全部内容(指标内容和按钮内容)容器高度
          $(`#page-${this.currentPagerPopupIndex}-description`).prepend(content) // 全部内容(指标内容和按钮内容)容器填充内容
        }
      }).finally(() => {
        this.popupContentLoading = false
      })
    },
    // popup指标内容实例化
    popupIndexContentInstance(data, label, buttonHeight) {
      const scalePopupAppearanceParametersConfig = {
        maxHeight: this.mapComp.mapPopupConfig.currentConfig.maxHeight * this.mapComp.mapComponentSizeScale['--scaleY'],
        titleHeight: this.mapComp.mapPopupConfig.currentConfig.titleHeight * this.mapComp.mapComponentSizeScale['--scaleY'],
        indexHeight: this.mapComp.mapPopupConfig.currentConfig.indexHeight * this.mapComp.mapComponentSizeScale['--scaleY'],
        pagerHeight: this.mapComp.mapPopupConfig.currentConfig.pagerHeight * this.mapComp.mapComponentSizeScale['--scaleY']
      }
      let popupIndexContentCalcHeight = 0 // popup内容指标部分计算高度参数
      const excludedIndex = ['topic_type', 'score', 'name', 'lng', 'lat', 'id'] // 配置需要排除展示的指标项(可扩展)
      let indexContentMaxHeight = scalePopupAppearanceParametersConfig.maxHeight * this.mapComp.mapPopupConfig.currentConfig.contentHeightProportion - scalePopupAppearanceParametersConfig.titleHeight - buttonHeight // 计算指标部分最大高度(计算公式:popup最大高度*popup内容部分高度与popup容器占比率值-标题部分高度-按钮部分高度)
      if (this.currentPagerPopupCount > 1) indexContentMaxHeight -= scalePopupAppearanceParametersConfig.pagerHeight // 存在分页时，指标内容最大高度重新计算(计算公式:指标内容最大高度=指标内容最大高度-页码部分高度)
      let indexContent = `<div class="index-container" style="max-height: ${indexContentMaxHeight}px;">`
      // 根据后台配置的label，遍历生成指标项实例
      if (label) {
        for (let key in label) {
          if (!data) break
          if (excludedIndex.includes(key)) continue // 配置排除展示的指标项过滤
          if (label[key] && data[key] && data[key] !== null && data[key] !== '') {
            let indexType = 1 // 指标类型参数，默认为1，可用值：1-文字描述；2-图片描述
            if (_const.mapConfigInfo.effectConfig.popupConfig.specialProcessingFieldCustomConfig.telephoneNumberDesensitizeField.includes(key)) {
              // 符合自定义配置的电话号码字段进行脱敏处理
              indexContent += `
                <p class="p-single-row">
                  <span>${label[key]}：</span>
                  ${desensitizeTeL(data[key])}
              `
              if (this.popupGeneralButtonsGenerateFlag.voiceCallButtonGenerateFlag) indexContent += `<span class="row-button-common row-button-phone" title="语音通话" onclick="voiceCall('${data[key]}', '${data['contact_person'] || data.name}')"></span>`
              indexContent += `</p>`
              popupIndexContentCalcHeight += this.calcPopupIndexContentHeight(label[key], data[key], indexType)
            } else if (_const.mapConfigInfo.effectConfig.popupConfig.specialProcessingFieldCustomConfig.imageConvertFields.urlField.includes(key) || _const.mapConfigInfo.effectConfig.popupConfig.specialProcessingFieldCustomConfig.imageConvertFields.base64Field.includes(key)) {
              // 图片相关字段特殊处理
              // 获取生成图片资源列表数组参数
              const separator = ',' // 图片资源字符串分隔符标识，默认为','
              let pictureList = []
              if (Array.isArray(data[key])) pictureList = data[key]
              else pictureList = data[key].split(separator)
              if (pictureList.length) {
                indexContent += `
                  <p class="p-multi-row">
                    <span>${label[key]}：</span>
                `
                if (pictureList.length > this.mapComp.mapPopupConfig.currentConfig.index.pictureMaxShowNUmber) {
                  // 图片数量超过popup设定的最大展示数量时，显示"查看更多"文字按钮
                  const subLabelName = '查看更多'
                  indexContent += `<span class="row-a-button-common" onclick="imageView('${key}','${this.mapComp.mapPopupConfig.currentConfig.index.pictureMaxShowNUmber}')">${subLabelName}</span>`
                }
                // 展示图片
                indexContent += `<a>`
                for (let index in pictureList) {
                  if (index > this.mapComp.mapPopupConfig.currentConfig.index.pictureMaxShowNUmber - 1) break
                  if (!pictureList[index]) continue
                  let pictureResources = null
                  if (_const.mapConfigInfo.effectConfig.popupConfig.specialProcessingFieldCustomConfig.imageConvertFields.urlField.includes(key)) {
                    pictureResources = `${window._CONFIG['domianURL']}/${pictureList[index]}`
                    if (pictureList[index].substring(0, 4) === 'http') pictureResources = pictureList[index]
                  } else if (_const.mapConfigInfo.effectConfig.popupConfig.specialProcessingFieldCustomConfig.imageConvertFields.base64Field.includes(key)) {
                    pictureResources = `data:image/png;base64,${pictureList[index]}`
                  } else {
                    pictureResources = ''
                  }
                  indexContent += `<img border="0" src=${pictureResources} alt="" onclick="imageView('${key}','${index}')">`
                }
                indexContent += `</a>`
                indexType = 2
                indexContent += `</p>`
                popupIndexContentCalcHeight += this.calcPopupIndexContentHeight(label[key], data[key], indexType)
              } else continue
            } else {
              let customFlag = false
              let customFieldIndex = 0
              for (const index in this.popupCustomFields) {
                if (this.currentShowPOIConfigDataDetail.layerName === this.popupCustomFields[index].layerName && key === this.popupCustomFields[index].fieldName) {
                  customFlag = true
                  customFieldIndex = index
                  indexContent += this.popupCustomFields[customFieldIndex].htmlTemplateElement.container.start
                  switch (this.popupCustomFields[customFieldIndex].showMatchedMode.type) {
                    case 'compare':
                      for (const item of this.popupCustomFields[customFieldIndex].dictionaryData) {
                        const compareValue = Number(item.value) - Number(data[key])
                        const contentKey = compareValue < this.popupCustomFields[customFieldIndex].showMatchedMode.matchValue ? 0 : compareValue === this.popupCustomFields[customFieldIndex].showMatchedMode.matchValue ? 1 : 2
                        const currentContentTemplate = this.popupCustomFields[customFieldIndex].htmlTemplateElement.content[contentKey]
                        for (const contentIndex in currentContentTemplate) {
                          if (currentContentTemplate[contentIndex]?.dynamicInsertValue) {
                            indexContent += currentContentTemplate[contentIndex].start
                            indexContent += item[currentContentTemplate[contentIndex].dynamicInsertValue]
                            indexContent += currentContentTemplate[contentIndex].end
                          } else indexContent += currentContentTemplate[contentIndex].start + currentContentTemplate[contentIndex].end
                        }
                      }
                      break
                  }
                  break
                }
              }
              if (customFlag) {
                indexContent += this.popupCustomFields[customFieldIndex].htmlTemplateElement.container.end
                popupIndexContentCalcHeight += this.popupCustomFields[customFieldIndex].htmlTemplateElement.container.height
              } else {
                indexContent += `<p><span>${label[key]}：</span>${data[key]}</p>`
                popupIndexContentCalcHeight += this.calcPopupIndexContentHeight(label[key], data[key], indexType)
              }
            }
          }
        }
      }
      if (popupIndexContentCalcHeight === 0) {
        // 指标项为空时，生成空内容实例
        popupIndexContentCalcHeight = scalePopupAppearanceParametersConfig.indexHeight // 获取指标部分配置默认(缺省)高度值
        indexContent += `
          <div class="empty" style="height: ${popupIndexContentCalcHeight}px;">
            <p>暂无详情</p>
          </div>
        `
      }
      indexContent += `</div>`
      const indexHeight = popupIndexContentCalcHeight > indexContentMaxHeight ? indexContentMaxHeight : popupIndexContentCalcHeight // 指标高度选取计算高度和最大高度二者间小者
      return { indexContent, indexHeight }
    },
    // 计算popup指标内容高度值
    calcPopupIndexContentHeight(label, value, indexType = 1) {
      const virtualPopupIndexContentRootNode = document.createElement('p') // 创建popup指标项虚拟根节点
      const virtualPopupIndexLabelNode = document.createElement('span') // 创建popup指标项名称虚拟节点
      virtualPopupIndexLabelNode.style['font-size'] = `${this.mapComp.mapPopupConfig.currentConfig.index.labelFontSize * this.mapComp.mapComponentSizeScale['--scaleFontRelative']}px`
      virtualPopupIndexLabelNode.innerHTML = `${label}：`
      virtualPopupIndexContentRootNode.appendChild(virtualPopupIndexLabelNode)
      virtualPopupIndexContentRootNode.style['width'] = `${this.mapComp.mapPopupConfig.currentConfig.index.width * this.mapComp.mapComponentSizeScale['--scaleX']}px`
      virtualPopupIndexContentRootNode.style['line-height'] = `${this.mapComp.mapPopupConfig.currentConfig.index.descriptionLineHeight * this.mapComp.mapComponentSizeScale['--scaleY']}px`
      virtualPopupIndexContentRootNode.style['font-size'] = `${this.mapComp.mapPopupConfig.currentConfig.index.descriptionFontSize * this.mapComp.mapComponentSizeScale['--scaleFontRelative']}px`
      virtualPopupIndexContentRootNode.style['position'] = 'fixed'
      virtualPopupIndexContentRootNode.style['visibility'] = 'hidden'
      virtualPopupIndexContentRootNode.style['z-index'] = '999'
      let virtualPopupIndexContentNode = document.createElement('text')
      if (indexType === 2) {
        virtualPopupIndexContentNode = document.createElement('img')
        virtualPopupIndexContentNode.style['display'] = 'block'
        virtualPopupIndexContentNode.style['width'] = `${this.mapComp.mapPopupConfig.currentConfig.index.width * this.mapComp.mapComponentSizeScale['--scaleX']}px`
        virtualPopupIndexContentNode.style['height'] = `${(this.mapComp.mapPopupConfig.currentConfig.index.pictureHeight + this.mapComp.mapPopupConfig.currentConfig.index.pictureMarginBottom) * this.mapComp.mapComponentSizeScale['--scaleY']}px`
      } else virtualPopupIndexContentNode.innerHTML = value
      virtualPopupIndexContentRootNode.appendChild(virtualPopupIndexContentNode)
      document.body.appendChild(virtualPopupIndexContentRootNode)
      const popupIndexContentHeight = this.getNumberFromStyleOfHeight(window.getComputedStyle(virtualPopupIndexContentRootNode).height)
      document.body.removeChild(virtualPopupIndexContentRootNode)
      return popupIndexContentHeight
    },
    // popup按钮内容实例化
    popupButtonContentInstance(layerName, layerId, data) {
      // 聚合类按钮处理逻辑
      let aggregatedButtonContent = '' // 定义聚合类按钮内容html片段参数，默认为''
      let aggregatedButtonHeight = 0 // 定义聚合类按钮比例高度参数，默认值为0
      let [...currentPopupCustomButtons] = this.popupCustomButtons // 深拷贝专题自定义按钮数组参数
      const aggregatedButtonFunctionName = 'searchSurroundingResources'
      let isLayerAggregatedButtonShow = false
      for (const index in currentPopupCustomButtons) {
        if (currentPopupCustomButtons[index].layerName === layerName && currentPopupCustomButtons[index].buttonFunctionName === aggregatedButtonFunctionName) {
          isLayerAggregatedButtonShow = true
          currentPopupCustomButtons.splice(index, 1)
          break
        }
      }
      if (isLayerAggregatedButtonShow || this.popupGeneralButtonsGenerateFlag.aggregatedButtonGenerateFlag) {
        // popup聚合类按钮配置展示时，执行相关处理逻辑
        // 周边搜索按钮
        // 配置展示按钮数组参数
        const searchSurroundingButtons = [
          // 周边1公里按钮
          {
            order: 1,
            buttonName: '1',
            buttonFunctionName: aggregatedButtonFunctionName,
            buttonFunctionParams: `1,${data.lat},${data.lng},1`
          },
          // 周边3公里按钮
          {
            order: 2,
            buttonName: '3',
            buttonFunctionName: aggregatedButtonFunctionName,
            buttonFunctionParams: `3,${data.lat},${data.lng},2`
          },
          // 周边5公里按钮
          {
            order: 3,
            buttonName: '5',
            buttonFunctionName: aggregatedButtonFunctionName,
            buttonFunctionParams: `5,${data.lat},${data.lng},3`
          },
          // 周边10公里按钮
          {
            order: 4,
            buttonName: '10',
            buttonFunctionName: aggregatedButtonFunctionName,
            buttonFunctionParams: `10,${data.lat},${data.lng},4`
          }
        ]
        aggregatedButtonHeight = this.mapComp.mapPopupConfig.currentConfig.button.aggregatedButtonRowHeight * this.mapComp.mapComponentSizeScale['--scaleY'] // 聚合类按钮行比例高度
        let additionalFilledHeight = 0
        if (!this.mapComp.mapPopupConfig.currentConfig.button.isSingleButtonShow) additionalFilledHeight = 10 * this.mapComp.mapComponentSizeScale['--scaleY']
        aggregatedButtonHeight = aggregatedButtonHeight + additionalFilledHeight
        aggregatedButtonContent = `<div style="height: ${aggregatedButtonHeight}px" class="aggregated-button-container">`
        aggregatedButtonContent += `<span>周边</span>`
        // 聚合按钮部分
        aggregatedButtonContent += `<div class="content">`
        // 聚合按钮面板
        aggregatedButtonContent += `<div class="button-plate-container">`
        aggregatedButtonContent += `<div class="color-ribbon"></div>` // 渐变色带
        // 按钮组
        aggregatedButtonContent += `<div class="button-plate">`
        for (const item of searchSurroundingButtons) {
          // 根据当前popup上的处于选中状态的周边搜索按钮排序号对象参数(currentOrderOfSurroundingSearchSelectedButtonOnPopup)取值，重建恢复按钮选中激活状态
          if (this.currentOrderOfSurroundingSearchSelectedButtonOnPopup?.id === `${data.id}` && this.currentOrderOfSurroundingSearchSelectedButtonOnPopup?.layerId === layerId && this.currentOrderOfSurroundingSearchSelectedButtonOnPopup?.buttonOrder === item.order) {
            aggregatedButtonContent += `<div id="searchSurroundingButton-${item.order}" class="button-common button-special-${item.order} button-selected" onclick="${item.buttonFunctionName}(${item.buttonFunctionParams})"></div>`
          } else aggregatedButtonContent += `<div id="searchSurroundingButton-${item.order}" class="button-common button-special-${item.order}" onclick="${item.buttonFunctionName}(${item.buttonFunctionParams})"></div>`
        }
        aggregatedButtonContent += `</div>`
        // 刻度线
        aggregatedButtonContent += `<div class="scale-line-common scale-line-plate">`
        aggregatedButtonContent += `<div class="scale-line-common scale-line-special-1"></div>`
        aggregatedButtonContent += `<div class="scale-line-common scale-line-special-2"></div>`
        aggregatedButtonContent += `<div class="scale-line-common scale-line-special-3"></div>`
        aggregatedButtonContent += `<div class="scale-line-common scale-line-special-4"></div>`
        aggregatedButtonContent += `</div>`
        aggregatedButtonContent += `</div>`
        // 按钮刻度面板
        aggregatedButtonContent += `<div class="scale-value-plate">`
        for (const item of searchSurroundingButtons) {
          aggregatedButtonContent += `<div class="scale-value-common scale-value-special-${item.order}">${item.buttonName}</div>`
        }
        aggregatedButtonContent += `</div>`
        aggregatedButtonContent += `</div>`
        aggregatedButtonContent += `<span>公里</span>`
        aggregatedButtonContent += `</div>`
      }
      // 单体类按钮处理逻辑
      let singleButtonContent = '' // 定义单体类按钮内容html片段参数，默认为''
      let singleButtonHeight = 0 // 定义单体类按钮比例高度参数，默认值为0
      if (this.mapComp.mapPopupConfig.currentConfig.button.isSingleButtonShow) {
        // popup单体类按钮配置展示时，执行相关处理逻辑
        // 接收传入参数并配置相关指标常量，作为相应按钮生成逻辑判定标识
        const videoCode = data['camera_code'] ? data['camera_code'] : null
        const videoPlayType = data['play_type'] ? data['play_type'] : '0'
        const videoName = data['camera_name'] ? data['camera_name'] : null
        const telephone = data['contact_phone'] ? data['contact_phone'] : null
        const liaison = data['contact_person'] ? data['contact_person'] : null
        const VRUrl = data['vr_url'] ? data['vr_url'] : null
        const name = data.name ? data.name : ''
        const id = data.id
        const singleButtonRowHeight = this.mapComp.mapPopupConfig.currentConfig.button.singleButtonRowHeight * this.mapComp.mapComponentSizeScale['--scaleY'] // 单体类按钮行比例高度
        let singleButtonContentBody = '' // 定义单体按钮内容内部html片段参数，初始为''
        let singleButtonCount = 0 // 设置单体按钮数量参数，初始为0
        // 指挥调度按钮
        const commandAndDeployButtonName = '指挥调度' // 配置指挥调度按钮名称
        let commandAndDeployCustomButtonFlag = false // 设置专题自定义的特殊(资源)指挥调度按钮实例生成标识，默认为false
        let commandAndDeployUniversalButtonFlag = false // 设置通用的指挥调度按钮实例生成标识，默认为false
        // 自定义的特殊(资源)指挥调度按钮实例生成逻辑
        for (let index in currentPopupCustomButtons) {
          // 遍历当前专题自定义按钮数组参数，查找当前图层是否存在专题自定义的特殊(资源)指挥调度按钮
          if (currentPopupCustomButtons[index].layerName === layerName && currentPopupCustomButtons[index].buttonName === commandAndDeployButtonName) {
            // 当前图层存在专题自定义的特殊(资源)指挥调度按钮时，按照按钮配置参数生成按钮实例
            if (currentPopupCustomButtons[index]?.buttonCreateJudgingConditions && Array.isArray(currentPopupCustomButtons[index].buttonCreateJudgingConditions) && currentPopupCustomButtons[index].buttonCreateJudgingConditions.length) {
              let buttonCreateFlag = true
              for (const subItem of currentPopupCustomButtons[index].buttonCreateJudgingConditions) {
                if (!subItem.conditionValues.includes(data[subItem.conditionName])) {
                  buttonCreateFlag = false
                  break
                }
              }
              if (!buttonCreateFlag) break
            }
            // 根据专题自定义的特殊(资源)指挥调度按钮实例标识，进行按钮实例生成
            if (commandAndDeployCustomButtonFlag) {
              currentPopupCustomButtons.splice(index, 1) // 当标识为true时，即图层数组中存在多个当前图层，需移除此按钮配置，避免出现生成多个按钮实例
            } else {
              // 当标识为false时，进行按钮实例生成
              singleButtonContentBody += `<button class="operate-button" onclick="${currentPopupCustomButtons[index].buttonFunctionName}('${layerId}')">${commandAndDeployButtonName}</button>`
              currentPopupCustomButtons.splice(index, 1) // 当前专题自定义按钮数组参数去除此自定义按钮配置对象参数
              commandAndDeployCustomButtonFlag = true // 专题自定义的特殊(资源)指挥调度按钮实例标识设置为true
            }
            break
          }
        }
        // 通用的指挥调度按钮实例生成逻辑(指挥调度按钮生成标识全局配置为true并且未生成专题自定义的特殊(资源)指挥调度按钮实例并且存在视频监控或者联系电话时)
        if (this.popupGeneralButtonsGenerateFlag.commandAndDeployButtonGenerateFlag && !commandAndDeployCustomButtonFlag && (telephone || videoCode)) {
          singleButtonContentBody += `<button class="operate-button" onclick="universalCommandAndDeploy('${videoCode}','${videoName || name}','${telephone}','${liaison || name}')">${commandAndDeployButtonName}</button>`
          commandAndDeployUniversalButtonFlag = true // 通用的指挥调度按钮实例生成标识设置为true
        }
        if (commandAndDeployCustomButtonFlag || commandAndDeployUniversalButtonFlag) singleButtonCount++ // 指挥调度按钮实例生成时，按钮数量自增1
        // 语音通话按钮
        if (this.popupGeneralButtonsGenerateFlag.voiceCallButtonGenerateFlag && telephone) {
          const buttonName = '语音通话' // 配置按钮名称
          singleButtonCount++
          singleButtonContentBody += `<button class="operate-button" onclick="voiceCall('${telephone}','${liaison || name}')">${buttonName}</button>`
        }
        // 实时视频按钮
        if (videoCode) {
          const buttonName = '实时视频' // 配置按钮名称
          singleButtonCount++
          singleButtonContentBody += `<button class="operate-button" onclick="showVideo('${videoCode}','${videoPlayType}')">${buttonName}</button>`
        }
        // 查看VR按钮
        if (VRUrl) {
          const buttonName = '查看VR' // 配置按钮名称
          singleButtonCount++
          singleButtonContentBody += `<button class="operate-button" onclick="showVR('${VRUrl}')">${buttonName}</button>`
        }
        // 专题自定义按钮
        for (const item of currentPopupCustomButtons) {
          if (item.layerName === layerName) {
            if (item?.buttonCreateJudgingConditions && Array.isArray(item.buttonCreateJudgingConditions) && item.buttonCreateJudgingConditions.length) {
              let buttonCreateFlag = true
              for (const subItem of item.buttonCreateJudgingConditions) {
                if (!subItem.conditionValues.includes(data[subItem.conditionName])) {
                  buttonCreateFlag = false
                  break
                }
              }
              if (!buttonCreateFlag) continue
            }
            singleButtonCount++
            singleButtonContentBody += `<button class="operate-button" onclick="${item.buttonFunctionName}('${layerId}','${id}','${name}',${item.buttonFunctionParams})">${item.buttonName}</button>`
          }
        }
        singleButtonContentBody += `</div>`
        const singleButtonContentHead = `<div class="${singleButtonCount > this.mapComp.mapPopupConfig.currentConfig.button.singleButtonRowLimit ? 'button-container button-container-multi-row' : 'button-container button-container-single-row'}">`
        singleButtonContent = singleButtonContentHead + singleButtonContentBody
        singleButtonHeight = singleButtonRowHeight * Math.ceil(singleButtonCount / this.mapComp.mapPopupConfig.currentConfig.button.singleButtonRowLimit)
      }
      // 计算按钮部分内容实例化相关参数
      const buttonContent = aggregatedButtonContent + singleButtonContent // html片段
      const buttonHeight = aggregatedButtonHeight + singleButtonHeight // 高度
      return { buttonContent, buttonHeight }
    },
    // (更多)图片查看
    imageView(type, viewInitialIndex) {
      const param = {
        images: this.currentShowPOIConfigDataDetail.data[type],
        title: `${this.currentShowPOIConfigDataDetail.labels[type]}浏览`,
        type: _const.mapConfigInfo.effectConfig.popupConfig.specialProcessingFieldCustomConfig.imageConvertFields.urlField.includes(type) ? 0 : 1,
        currentIndex: viewInitialIndex
      }
      this.$eventBus.$emit('imageView', param)
    },
    // 通用的指挥调度按钮点击响应
    universalCommandAndDeploy(cameraCode, cameraName, telephoneNumber, contactPersonName) {
      let param = {}
      // 区分视频(监控)和电话(联系方式)两种调度类型,优先进行视频(监控)调度,其次为电话(联系方式)调度
      if (cameraCode && cameraCode !== 'null' && cameraCode !== 'undefined') {
        param = {
          eventBusType: 'camera',
          cameraCode: cameraCode,
          cameraName: cameraName
        }
      } else if (telephoneNumber && telephoneNumber !== 'null' && telephoneNumber !== 'undefined') {
        param = {
          eventBusType: 'person',
          contactPersonPhoneNumber: telephoneNumber,
          contactPersonName: contactPersonName
        }
      } else return
      this.$eventBus.$emit('addToMeetting', param) // 向指挥调度面板发送指令
    },
    // 特殊的(资源)指挥调度按钮点击响应
    resourceCommandAndDeploy(layerId) {
      const eventBusParam = {
        eventBusType: 'resource',
        data: { ...this.currentShowPOIConfigDataDetail.data, ...{ layerId }},
        label: this.currentShowPOIConfigDataDetail.labels
      }
      this.$eventBus.$emit('addToMeetting', eventBusParam) // 向指挥调度面板发送指令
    },
    // 语音通话按钮点击响应
    voiceCall(telephoneNumber, contactPersonName) {
      const param = {
        telephone: telephoneNumber,
        name: contactPersonName
      }
      this.$eventBus.$emit('singleCall', param) // 向单点通话面板发送指令
    },
    // 查看实时视频按钮点击响应
    showVideo(code, playType) {
      const videoPlayType = Number(playType)
      switch (videoPlayType) {
        case 0:
          this.mapComp.dataLoading = true
          cameraDetail({ cameraCode: code }).then(res => {
            if (res.success) this.$eventBus.$emit('showVideoDialog', { type: videoPlayType, url: res.result.playUrl.flvUrl, code })
            else this.$message.warning(res.message)
          }).finally(() => {
            this.mapComp.dataLoading = false
          })
          break
        case 1:
          this.$eventBus.$emit('showVideoDialog', { type: videoPlayType, code })
          break
      }
    },
    // 查看VR按钮点击响应
    showVR(VRUrl) {
      this.$eventBus.$emit('openWebpageTab', VRUrl)
    },
    // 指定POI高亮显示
    openPOIHighlight(data, isUniqueShow = true, isKeepSearchValue = false, isDynamicLayer = false) {
      data.id = data.id + ''
      const { lng, lat, id, layerId } = data
      // 获取高亮POI全部属性(attr)参数，构建高亮POI属性参数对象
      const propertyOfHighlightPOI = {}
      const excludedParameterList = ['lng', 'lat', 'isUniqueShow', 'isClusterPoint'] // 排除参数列表
      for (const key in data) {
        if (!excludedParameterList.includes(key)) {
          propertyOfHighlightPOI[key] = data[key] // 遍历数据，向高亮POI属性参数对象添加传递参数
        }
      }
      this.propertyOfAllPOISOnCurrentShowPopup = [propertyOfHighlightPOI] // 为全局的当前展示popup的所包含全部POI的属性信息数组参数(propertyOfAllPOISOnCurrentShowPopup)重新赋值
      this.currentShowPopupPOIProperty = { id, layerId }
      if (isUniqueShow) this.currentShowPopupPOIProperty.isUniqueShowPOI = true // POI单独唯一展示时，为当前展示popup的POI对应的属性对象参数currentShowPopupPOIProperty追加设置标识属性isUniqueShowPOI为true
      if (!isKeepSearchValue) this.activeSearchValue = '' // 传参isKeepSearchValue为false时，重置全局参数activeSearchValue
      // 判断当前要高亮的POI所在图层是否处于活动(选中)状态(注：动态图层默认为处于活动(选中)状态)
      let isLayerShow = false
      if (this.activeBindingLayerIds.includes(layerId) || isDynamicLayer) {
        isLayerShow = true
      } else {
        // 当前要高亮的POI所在图层处于非活动(未选中)状态时，更新活动的绑定图层数组参数
        if (this.activateBindingLayerMode) {
          // 单选模式下，根据当前要高亮的POI所在图层展示模式进行绑定图层数组参数更新
          if (this.mapComp.getPOILayerMode(layerId, 'show')) {
            // 当前要高亮的POI所在图层展示模式为显式展示模式时，需剔除活动的绑定图层数组参数中的显式展示模式的POI图层(保证单选模式下显式展示模式的图层仅选中一个)
            const activeBindingHiddenLayerIds = this.activeBindingLayerIds.filter(item => {
              return !this.mapComp.getPOILayerMode(item, 'show')
            })
            this.activeBindingLayerIds = [...activeBindingHiddenLayerIds]
          }
        }
        this.activeBindingLayerIds.push(layerId)
        this.$eventBus.$emit('externalTriggerOfPOILayerSelectedStatusChange', { layerId }) // 发射选中图层变化事件至POI图层管理组件(POILayerManagement)中，进行数据驱动更新
      }
      const mapStatusParam = { lng, lat }
      if (this.isMapCenterWithTheLocation(mapStatusParam)) {
        // 当前地图姿态满足地图居中位置阈值要求时
        // 检查待高亮的POI在其所在图层存在情况
        const graphic = this.mapComp.businessLayers.POILayer[this.currentShowPopupPOIProperty.layerId].getGraphicByAttr(this.currentShowPopupPOIProperty.id, 'id')
        if (graphic && isLayerShow) {
          // 待高亮的POI存在且要高亮的POI所在图层处于活动(选中)状态时
          this.reserveCurrentShowPopupPOIPropertyFlag = true // 设置全局参数保留当前展示popup的POI对应的属性对象的标识参数(reserveCurrentShowPopupPOIPropertyFlag)为true，避免当前待高亮POI的属性对象被清空
          this.mapClickEventFlag = false // 重置点击地图空白标识参数为false，避免干扰导致异常
          this.map.closePopup() // 关闭popup(若存在)
          this.rediscoverCurrentShowPopupPOI() // 重发现POI
        } else {
          // 待高亮的POI不存在或要高亮的POI所在图层处于不活动(未选中)状态时
          if (!isDynamicLayer) this.loadPOIData(this.activeBindingLayerIds) // 非动态图层，进行POI数据更新
          else this.$eventBus.$emit('dynamicLayerLoadPOIData') // 动态图层，进行动态图层数据更新事件发射
        }
      } else {
        this.mapStatusSwitch(2, mapStatusParam, true) // 当前地图姿态满足地图居中位置阈值未满足要求时，执行地图姿态控制逻辑
      }
    },
    // 地图姿态控制
    mapStatusSwitch(statusCode, statusParam, globalPropertyRestore = false) {
      const switchResult = this.mapComp.switchMapStatus(statusCode, statusParam) // 执行地图姿态切换，以触发图层数据刷新事件机制
      if (switchResult !== 1) {
        // 当地图姿态切换未执行成功时，根据返回码进行信息提示并回滚相关参数
        if (switchResult === 0) this.$message.warning('当前地图视角无法响应此操作，请调整地图视角后重试！')
        if (globalPropertyRestore) this.currentShowPopupPOIProperty = {}
      }
    },
    // 搜索周围资源
    searchSurroundingResources(radius, lat, lng, buttonOrder = null) {
      // 根据周边资源展示面板配置项，处理对应逻辑
      if (this.useBuiltInSurroundingSearchShowDialog) {
        // 地图内置周边搜索组件面板
        this.currentSurroundingSearchCircle = { radius, lat, lng } // 参数暂存，用于组件传参
        // 根据搜索半径，确定默认展示图层首选项配置值
        this.surroundingSearchResultPreferenceCustomSetting = 0 // 默认首选项为0(即全部图层)
        if (radius > 1) {
          // 搜索半径大于1km时
          this.surroundingSearchResultPreferenceCustomSetting = 1 // 首选项配置为1(即首图层)
          this.currentSurroundingSearchCircle.layerIdList = [this.bindingLayerGroups[0].layerInfoList[0].id] // 配置查询首图层id
        }
      } else {
        // 外部视频资源展示面板
        this.mapComp.dataLoading = true
        const prescriptiveLayerId = _const.cameraLayerId // 指定的图层id，当前为视频监控图层
        // 设置外传信息对象参数
        const transitiveInfo = {
          searchShape: {
            type: 'circle', // 当前指定为圆形
            radius: radius // 半径
          }, // 图形搜索形状相关信息
          searchReferencedPOIDataDetail: this.currentShowPOIConfigDataDetail // 搜索基准POI数据详情信息
        }
        const params = {
          topicType: this.topicType,
          needGroup: false,
          circleRadius: radius,
          circlePoint: {
            fragment: true,
            geohash: '',
            lat: lat,
            lon: lng
          },
          layerIdList: [prescriptiveLayerId]
        }
        getPOIDataByParams(params).then(res => {
          transitiveInfo.searchCameraList = res.result && res.result[prescriptiveLayerId] ? res.result[prescriptiveLayerId] : []
          if (res.success) this.$eventBus.$emit('showAroundCameraDialog', transitiveInfo) // 发射额外的指令，提供数据给外部视频资源展示面板
        }).finally(() => {
          this.mapComp.dataLoading = false
        })
      }
      this.addSearchSurroundingResourcesMarkOnMap(radius, lat, lng, buttonOrder)
    },
    // 增加周围资源搜索地图痕迹(圈画和按钮选中状态)
    addSearchSurroundingResourcesMarkOnMap(radius, lat, lng, buttonOrder) {
      this.clearSearchSurroundingResourcesMarkOnMap(buttonOrder)
      this.createSurroundingSearchLayer()
      const graphicColor = this.getColorByRadius(radius)
      const graphic = new this.$Imap.graphic.CircleEntity({
        position: [lng, lat],
        style: {
          radius: radius * 1000,
          color: graphicColor,
          opacity: 0.2,
          outline: true,
          outlineWidth: 3,
          outlineColor: graphicColor,
          clampToGround: false
        }
      })
      this.mapComp.businessLayers.dataLayer[this.surroundingSearchCircleLayerName].addGraphic(graphic)
      this.mapComp.businessLayers.dataLayer[this.surroundingSearchCircleLayerName].on('click', () => {
        this.mapClickEventFlag = true // 设置点击地图空白标识参数为true，避免导致点击到实体(圈画图形)无法正常关闭popup
      })
      this.mapComp.businessLayers.dataLayer[this.surroundingSearchCircleLayerName].on('mouseOver', () => {
        this.map.setCursor(this.mapComp.mapDefaultCursor) // 设置鼠标样式为默认
      })
    },
    // 创建周边搜索圈画数据图层
    createSurroundingSearchLayer() {
      if (!this.mapComp.businessLayers.dataLayer[this.surroundingSearchCircleLayerName]) {
        this.mapComp.businessLayers.dataLayer[this.surroundingSearchCircleLayerName] = new this.$Imap.layer.GraphicLayer()
        this.map.addLayer(this.mapComp.businessLayers.dataLayer[this.surroundingSearchCircleLayerName])
      }
    },
    // 根据半径匹配地图痕迹(画圈)颜色
    getColorByRadius(radius) {
      const defaultColor = '#00ffff'
      const colorLibrary = {
        1: '#e60012',
        3: '#f7ab00',
        5: '#fff100',
        10: '#02f061'
      }
      return colorLibrary[radius] || defaultColor
    },
    // 清除周围资源搜索地图痕迹(圈画和按钮选中状态)
    clearSearchSurroundingResourcesMarkOnMap(orderOfSearchSurroundingResourcesButtonOnPopup) {
      if (this.mapComp.businessLayers.dataLayer[this.surroundingSearchCircleLayerName]) this.mapComp.clearDataLayer(this.surroundingSearchCircleLayerName)
      this.updateStatusWithSearchSurroundingResourcesButtonOnPopup(orderOfSearchSurroundingResourcesButtonOnPopup)
    },
    // 更新POI的popup上周边搜索按钮选中状态
    updateStatusWithSearchSurroundingResourcesButtonOnPopup(buttonOrder) {
      // 清除当前按钮选中状态(若存在)
      if (JSON.stringify(this.currentOrderOfSurroundingSearchSelectedButtonOnPopup) !== '{}' && document.getElementById(`searchSurroundingButton-${this.currentOrderOfSurroundingSearchSelectedButtonOnPopup.buttonOrder}`)) {
        document.getElementById(`searchSurroundingButton-${this.currentOrderOfSurroundingSearchSelectedButtonOnPopup.buttonOrder}`).className = `button-common button-special-${this.currentOrderOfSurroundingSearchSelectedButtonOnPopup.buttonOrder}`
      }
      // 未传参为重置操作
      if (!buttonOrder) {
        this.currentOrderOfSurroundingSearchSelectedButtonOnPopup = {}
        return
      }
      // 传参时为更新操作
      this.currentOrderOfSurroundingSearchSelectedButtonOnPopup = {
        buttonOrder,
        id: this.currentShowPopupPOIProperty.id,
        layerId: this.currentShowPopupPOIProperty.layerId
      }
      document.getElementById(`searchSurroundingButton-${this.currentOrderOfSurroundingSearchSelectedButtonOnPopup.buttonOrder}`).className = `button-common button-special-${this.currentOrderOfSurroundingSearchSelectedButtonOnPopup.buttonOrder} button-selected`
    },
    // 图形查询统计结果展示
    showSummaryOfPOIDataByGraphicOnMap(data, openPosition, searchParams) {
      this.paramsOfTransitiveFunction = [searchParams] // 获取当前查询参数用于传参
      let summary = 0
      for (let index in data) summary = summary + data[index].length // 计算统计数据数量
      const template = `<div class="map-graphic-search-summary">
        <div class="content">
          <p class="title">区域内共找到<span class="summary">${summary}</span>${this.customDescriptionInSummaryOfPOIDataByGraphicOnMap}</p>
          <div class="mark" title="点击查看详情" onclick="showPOIDataDetailByGraphic()"></div>
        </div>
        <div class="icon"></div>
      </div>`
      const graphic = new this.$Imap.graphic.DivGraphic({
        position: [openPosition.lng, openPosition.lat],
        pointerEvents: true,
        style: {
          html: template,
          horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
          verticalOrigin: Cesium.HorizontalOrigin.BOTTOM
        }
      })
      this.map.graphicLayer.addGraphic(graphic)
      this.mapComp.dataLoading = false
    },
    // 从css的height属性值从获取高度数值
    getNumberFromStyleOfHeight(heightString) {
      let number = 0
      if (heightString.indexOf('px') > 0) {
        number = parseInt(heightString.split('px')[0])
      }
      return number
    },
    // 判断传入位置(经纬度)是否为当前地图中心位置
    isMapCenterWithTheLocation({ lat, lng, alt }) {
      const latLngBufferCalculationLevelCoefficient = typeof (alt) === 'undefined' ? this.frontClusterStartLevel : this.map.level
      const latBuffer = `${_const.mapConfigInfo.interactConfig.popupAvoidObstructBuffer.lat * Math.pow(2, (_const.mapConfigInfo.basicConfig.maxZoom - latLngBufferCalculationLevelCoefficient))}`
      const lngBuffer = `${_const.mapConfigInfo.interactConfig.popupAvoidObstructBuffer.lng * Math.pow(2, (_const.mapConfigInfo.basicConfig.maxZoom - latLngBufferCalculationLevelCoefficient))}`
      if (Math.abs(Math.round(lat * Math.pow(10, 6)) / Math.pow(10, 6) - this.map.getCenter().lat).toFixed(6) <= Math.abs(latBuffer) && Math.abs(Math.round(lng * Math.pow(10, 6)) / Math.pow(10, 6) - this.map.getCenter().lng).toFixed(6) <= Math.abs(lngBuffer)) return true
      else return false
    }
  }
}
